summaryrefslogtreecommitdiff
path: root/ipc/dbus
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/dbus')
-rw-r--r--ipc/dbus/DBusConnectionDelete.h42
-rw-r--r--ipc/dbus/DBusConnectionRefPtr.h40
-rw-r--r--ipc/dbus/DBusHelpers.cpp246
-rw-r--r--ipc/dbus/DBusHelpers.h65
-rw-r--r--ipc/dbus/DBusMessageRefPtr.h30
-rw-r--r--ipc/dbus/DBusPendingCallRefPtr.h30
-rw-r--r--ipc/dbus/DBusUtils.cpp99
-rw-r--r--ipc/dbus/DBusUtils.h105
-rw-r--r--ipc/dbus/DBusWatcher.cpp149
-rw-r--r--ipc/dbus/DBusWatcher.h50
-rw-r--r--ipc/dbus/RawDBusConnection.cpp114
-rw-r--r--ipc/dbus/RawDBusConnection.h54
-rw-r--r--ipc/dbus/moz.build33
13 files changed, 1057 insertions, 0 deletions
diff --git a/ipc/dbus/DBusConnectionDelete.h b/ipc/dbus/DBusConnectionDelete.h
new file mode 100644
index 0000000000..80e47d14e3
--- /dev/null
+++ b/ipc/dbus/DBusConnectionDelete.h
@@ -0,0 +1,42 @@
+/* -*- 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_DBusConnectionDelete_h
+#define mozilla_ipc_DBusConnectionDelete_h
+
+#include <dbus/dbus.h>
+#include "mozilla/UniquePtr.h"
+
+namespace mozilla {
+
+/*
+ * |DBusConnectionDelete| is a deleter for managing instances
+ * of |DBusConnection| in |UniquePtr|. Upon destruction, it
+ * will close an open connection before unref'ing the data
+ * structure.
+ *
+ * Do not use |UniquePtr| with shared DBus connections. For
+ * shared connections, use |RefPtr|.
+ */
+class DBusConnectionDelete
+{
+public:
+ constexpr DBusConnectionDelete()
+ { }
+
+ void operator()(DBusConnection* aConnection) const
+ {
+ MOZ_ASSERT(aConnection);
+ if (dbus_connection_get_is_connected(aConnection)) {
+ dbus_connection_close(aConnection);
+ }
+ dbus_connection_unref(aConnection);
+ }
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ipc_DBusConnectionDelete_h
diff --git a/ipc/dbus/DBusConnectionRefPtr.h b/ipc/dbus/DBusConnectionRefPtr.h
new file mode 100644
index 0000000000..93bf115d9e
--- /dev/null
+++ b/ipc/dbus/DBusConnectionRefPtr.h
@@ -0,0 +1,40 @@
+/* -*- 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_DBusConnectionRefPtr_h
+#define mozilla_ipc_DBusConnectionRefPtr_h
+
+#include <dbus/dbus.h>
+#include "mozilla/RefPtr.h"
+
+namespace mozilla {
+
+/*
+ * |RefPtrTraits<DBusConnection>| specializes |RefPtrTraits<>|
+ * for managing |DBusConnection| with |RefPtr|.
+ *
+ * |RefPtrTraits<DBusConnection>| will _not_ close the DBus
+ * connection upon the final unref. The caller is responsible
+ * for closing the connection.
+ *
+ * See |DBusConnectionDelete| for auto-closing of connections.
+ */
+template<>
+struct RefPtrTraits<DBusConnection>
+{
+ static void AddRef(DBusConnection* aConnection) {
+ MOZ_ASSERT(aConnection);
+ dbus_connection_ref(aConnection);
+ }
+ static void Release(DBusConnection* aConnection) {
+ MOZ_ASSERT(aConnection);
+ dbus_connection_unref(aConnection);
+ }
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ipc_DBusConnectionRefPtr_h
diff --git a/ipc/dbus/DBusHelpers.cpp b/ipc/dbus/DBusHelpers.cpp
new file mode 100644
index 0000000000..73b4596f29
--- /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;
+}
+
+}
+}
diff --git a/ipc/dbus/DBusHelpers.h b/ipc/dbus/DBusHelpers.h
new file mode 100644
index 0000000000..dc5212971a
--- /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
diff --git a/ipc/dbus/DBusMessageRefPtr.h b/ipc/dbus/DBusMessageRefPtr.h
new file mode 100644
index 0000000000..525463a4ca
--- /dev/null
+++ b/ipc/dbus/DBusMessageRefPtr.h
@@ -0,0 +1,30 @@
+/* -*- 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_DBusMessageRefPtr_h
+#define mozilla_ipc_DBusMessageRefPtr_h
+
+#include <dbus/dbus.h>
+#include "mozilla/RefPtr.h"
+
+namespace mozilla {
+
+template<>
+struct RefPtrTraits<DBusMessage>
+{
+ static void AddRef(DBusMessage* aMessage) {
+ MOZ_ASSERT(aMessage);
+ dbus_message_ref(aMessage);
+ }
+ static void Release(DBusMessage* aMessage) {
+ MOZ_ASSERT(aMessage);
+ dbus_message_unref(aMessage);
+ }
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ipc_DBusMessageRefPtr_h
diff --git a/ipc/dbus/DBusPendingCallRefPtr.h b/ipc/dbus/DBusPendingCallRefPtr.h
new file mode 100644
index 0000000000..54e4cfd7c6
--- /dev/null
+++ b/ipc/dbus/DBusPendingCallRefPtr.h
@@ -0,0 +1,30 @@
+/* -*- 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_DBusPendingCallRefPtr_h
+#define mozilla_ipc_DBusPendingCallRefPtr_h
+
+#include <dbus/dbus.h>
+#include "mozilla/RefPtr.h"
+
+namespace mozilla {
+
+template<>
+struct RefPtrTraits<DBusPendingCall>
+{
+ static void AddRef(DBusPendingCall* aPendingCall) {
+ MOZ_ASSERT(aPendingCall);
+ dbus_pending_call_ref(aPendingCall);
+ }
+ static void Release(DBusPendingCall* aPendingCall) {
+ MOZ_ASSERT(aPendingCall);
+ dbus_pending_call_unref(aPendingCall);
+ }
+};
+
+} // namespace mozilla
+
+#endif // mozilla_ipc_DBusPendingCallRefPtr_h
diff --git a/ipc/dbus/DBusUtils.cpp b/ipc/dbus/DBusUtils.cpp
new file mode 100644
index 0000000000..6e36bca0fe
--- /dev/null
+++ b/ipc/dbus/DBusUtils.cpp
@@ -0,0 +1,99 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/*
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <dbus/dbus.h>
+#include "DBusUtils.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 {
+
+//
+// DBusMessageRefPtr
+//
+
+DBusMessageRefPtr::DBusMessageRefPtr(DBusMessage* aMsg)
+ : mMsg(aMsg)
+{
+ if (mMsg) {
+ dbus_message_ref(mMsg);
+ }
+}
+
+DBusMessageRefPtr::~DBusMessageRefPtr()
+{
+ if (mMsg) {
+ dbus_message_unref(mMsg);
+ }
+}
+
+//
+// DBusReplyHandler
+//
+
+void DBusReplyHandler::Callback(DBusMessage* aReply, void* aData)
+{
+ MOZ_ASSERT(aData);
+
+ RefPtr<DBusReplyHandler> handler =
+ already_AddRefed<DBusReplyHandler>(static_cast<DBusReplyHandler*>(aData));
+
+ handler->Handle(aReply);
+}
+
+//
+// Utility functions
+//
+
+void
+log_and_free_dbus_error(DBusError* err, const char* function, DBusMessage* msg)
+{
+ if (msg) {
+ CHROMIUM_LOG("%s: D-Bus error in %s: %s (%s)", function,
+ dbus_message_get_member((msg)), (err)->name, (err)->message);
+ } else {
+ CHROMIUM_LOG("%s: D-Bus error: %s (%s)", __FUNCTION__,
+ (err)->name, (err)->message);
+ }
+ dbus_error_free((err));
+}
+
+int dbus_returns_int32(DBusMessage *reply)
+{
+ DBusError err;
+ int32_t ret = -1;
+
+ dbus_error_init(&err);
+ if (!dbus_message_get_args(reply, &err,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_INVALID)) {
+ LOG_AND_FREE_DBUS_ERROR_WITH_MSG(&err, reply);
+ }
+
+ return ret;
+}
+
+}
+}
diff --git a/ipc/dbus/DBusUtils.h b/ipc/dbus/DBusUtils.h
new file mode 100644
index 0000000000..8d80f1f87c
--- /dev/null
+++ b/ipc/dbus/DBusUtils.h
@@ -0,0 +1,105 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/*
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#ifndef mozilla_ipc_dbus_dbusutils_h__
+#define mozilla_ipc_dbus_dbusutils_h__
+
+#include <dbus/dbus.h>
+#include "mozilla/RefPtr.h"
+#include "nsISupportsImpl.h"
+
+// LOGE and free a D-Bus error
+// Using #define so that __FUNCTION__ resolves usefully
+#define LOG_AND_FREE_DBUS_ERROR_WITH_MSG(err, msg) log_and_free_dbus_error(err, __FUNCTION__, msg);
+#define LOG_AND_FREE_DBUS_ERROR(err) log_and_free_dbus_error(err, __FUNCTION__);
+
+namespace mozilla {
+namespace ipc {
+
+class DBusMessageRefPtr
+{
+public:
+ explicit DBusMessageRefPtr(DBusMessage* aMsg);
+ ~DBusMessageRefPtr();
+
+ operator DBusMessage* ()
+ {
+ return mMsg;
+ }
+
+ DBusMessage* get()
+ {
+ return mMsg;
+ }
+
+private:
+ DBusMessage* mMsg;
+};
+
+/**
+ * DBusReplyHandler represents a handler for DBus reply messages. Inherit
+ * from this class and implement the Handle method. The method Callback
+ * should be passed to the DBus send function, with the class instance as
+ * user-data argument.
+ */
+class DBusReplyHandler
+{
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DBusReplyHandler)
+
+ /**
+ * Implements a call-back function for DBus. The supplied value for
+ * aData must be a pointer to an instance of DBusReplyHandler.
+ */
+ static void Callback(DBusMessage* aReply, void* aData);
+
+ /**
+ * Call-back method for handling the reply message from DBus.
+ */
+ virtual void Handle(DBusMessage* aReply) = 0;
+
+protected:
+ DBusReplyHandler()
+ {
+ }
+
+ DBusReplyHandler(const DBusReplyHandler& aHandler)
+ {
+ }
+
+ DBusReplyHandler& operator = (const DBusReplyHandler& aRhs)
+ {
+ return *this;
+ }
+
+ virtual ~DBusReplyHandler()
+ {
+ }
+};
+
+void log_and_free_dbus_error(DBusError* err,
+ const char* function,
+ DBusMessage* msg = nullptr);
+
+int dbus_returns_int32(DBusMessage *reply);
+
+}
+}
+
+#endif
+
diff --git a/ipc/dbus/DBusWatcher.cpp b/ipc/dbus/DBusWatcher.cpp
new file mode 100644
index 0000000000..1caeab3bb1
--- /dev/null
+++ b/ipc/dbus/DBusWatcher.cpp
@@ -0,0 +1,149 @@
+/* -*- 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 "DBusWatcher.h"
+#include "mozilla/Unused.h"
+#include "nsThreadUtils.h"
+
+namespace mozilla {
+namespace ipc {
+
+DBusWatcher::DBusWatcher(DBusConnection* aConnection, DBusWatch* aWatch)
+ : mConnection(aConnection)
+ , mWatch(aWatch)
+{
+ MOZ_ASSERT(mConnection);
+ MOZ_ASSERT(mWatch);
+}
+
+DBusWatcher::~DBusWatcher()
+{ }
+
+DBusConnection*
+DBusWatcher::GetConnection()
+{
+ return mConnection;
+}
+
+void
+DBusWatcher::StartWatching()
+{
+ MOZ_ASSERT(!NS_IsMainThread());
+
+ auto flags = dbus_watch_get_flags(mWatch);
+
+ if (!(flags & (DBUS_WATCH_READABLE|DBUS_WATCH_WRITABLE))) {
+ return;
+ }
+
+ auto ioLoop = MessageLoopForIO::current();
+
+ auto fd = dbus_watch_get_unix_fd(mWatch);
+
+ if (flags & DBUS_WATCH_READABLE) {
+ ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_READ,
+ &mReadWatcher, this);
+ }
+ if (flags & DBUS_WATCH_WRITABLE) {
+ ioLoop->WatchFileDescriptor(fd, true, MessageLoopForIO::WATCH_WRITE,
+ &mWriteWatcher, this);
+ }
+}
+
+void
+DBusWatcher::StopWatching()
+{
+ MOZ_ASSERT(!NS_IsMainThread());
+
+ auto flags = dbus_watch_get_flags(mWatch);
+
+ if (flags & DBUS_WATCH_READABLE) {
+ mReadWatcher.StopWatchingFileDescriptor();
+ }
+ if (flags & DBUS_WATCH_WRITABLE) {
+ mWriteWatcher.StopWatchingFileDescriptor();
+ }
+}
+
+// DBus utility functions, used as function pointers in DBus setup
+
+void
+DBusWatcher::FreeFunction(void* aData)
+{
+ UniquePtr<DBusWatcher> watcher(static_cast<DBusWatcher*>(aData));
+}
+
+dbus_bool_t
+DBusWatcher::AddWatchFunction(DBusWatch* aWatch, void* aData)
+{
+ MOZ_ASSERT(!NS_IsMainThread());
+
+ auto connection = static_cast<DBusConnection*>(aData);
+
+ UniquePtr<DBusWatcher> dbusWatcher =
+ MakeUnique<DBusWatcher>(connection, aWatch);
+
+ dbus_watch_set_data(aWatch, dbusWatcher.get(), DBusWatcher::FreeFunction);
+
+ if (dbus_watch_get_enabled(aWatch)) {
+ dbusWatcher->StartWatching();
+ }
+
+ Unused << dbusWatcher.release(); // picked up in |FreeFunction|
+
+ return TRUE;
+}
+
+void
+DBusWatcher::RemoveWatchFunction(DBusWatch* aWatch, void* aData)
+{
+ MOZ_ASSERT(!NS_IsMainThread());
+
+ auto dbusWatcher = static_cast<DBusWatcher*>(dbus_watch_get_data(aWatch));
+
+ dbusWatcher->StopWatching();
+}
+
+void
+DBusWatcher::ToggleWatchFunction(DBusWatch* aWatch, void* aData)
+{
+ MOZ_ASSERT(!NS_IsMainThread());
+
+ auto dbusWatcher = static_cast<DBusWatcher*>(dbus_watch_get_data(aWatch));
+
+ if (dbus_watch_get_enabled(aWatch)) {
+ dbusWatcher->StartWatching();
+ } else {
+ dbusWatcher->StopWatching();
+ }
+}
+
+// I/O-loop callbacks
+
+void
+DBusWatcher::OnFileCanReadWithoutBlocking(int aFd)
+{
+ MOZ_ASSERT(!NS_IsMainThread());
+
+ dbus_watch_handle(mWatch, DBUS_WATCH_READABLE);
+
+ DBusDispatchStatus dbusDispatchStatus;
+
+ do {
+ dbusDispatchStatus = dbus_connection_dispatch(mConnection);
+ } while (dbusDispatchStatus == DBUS_DISPATCH_DATA_REMAINS);
+}
+
+void
+DBusWatcher::OnFileCanWriteWithoutBlocking(int aFd)
+{
+ MOZ_ASSERT(!NS_IsMainThread());
+
+ dbus_watch_handle(mWatch, DBUS_WATCH_WRITABLE);
+}
+
+} // namespace ipc
+} // namespace mozilla
diff --git a/ipc/dbus/DBusWatcher.h b/ipc/dbus/DBusWatcher.h
new file mode 100644
index 0000000000..d866e61583
--- /dev/null
+++ b/ipc/dbus/DBusWatcher.h
@@ -0,0 +1,50 @@
+/* -*- 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_DBusWatcher_h
+#define mozilla_ipc_DBusWatcher_h
+
+#include <dbus/dbus.h>
+#include "base/message_loop.h"
+
+namespace mozilla {
+namespace ipc {
+
+class DBusWatcher : public MessageLoopForIO::Watcher
+{
+public:
+ DBusWatcher(DBusConnection* aConnection, DBusWatch* aWatch);
+ ~DBusWatcher();
+
+ void StartWatching();
+ void StopWatching();
+
+ static void FreeFunction(void* aData);
+ static dbus_bool_t AddWatchFunction(DBusWatch* aWatch, void* aData);
+ static void RemoveWatchFunction(DBusWatch* aWatch, void* aData);
+ static void ToggleWatchFunction(DBusWatch* aWatch, void* aData);
+
+ DBusConnection* GetConnection();
+
+private:
+ void OnFileCanReadWithoutBlocking(int aFd);
+ void OnFileCanWriteWithoutBlocking(int aFd);
+
+ // Read watcher for libevent. Only to be accessed on IO Thread.
+ MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
+
+ // Write watcher for libevent. Only to be accessed on IO Thread.
+ MessageLoopForIO::FileDescriptorWatcher mWriteWatcher;
+
+ // DBus structures
+ DBusConnection* mConnection;
+ DBusWatch* mWatch;
+};
+
+} // namespace ipc
+} // namespace mozilla
+
+#endif // mozilla_ipc_DBusWatcher_h
diff --git a/ipc/dbus/RawDBusConnection.cpp b/ipc/dbus/RawDBusConnection.cpp
new file mode 100644
index 0000000000..420ecfe445
--- /dev/null
+++ b/ipc/dbus/RawDBusConnection.cpp
@@ -0,0 +1,114 @@
+/* -*- 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"
+
+namespace mozilla {
+namespace ipc {
+
+//
+// RawDBusConnection
+//
+
+bool RawDBusConnection::sDBusIsInit(false);
+
+RawDBusConnection::RawDBusConnection()
+{
+}
+
+RawDBusConnection::~RawDBusConnection()
+{
+}
+
+nsresult RawDBusConnection::EstablishDBusConnection()
+{
+ if (!sDBusIsInit) {
+ dbus_bool_t success = dbus_threads_init_default();
+ NS_ENSURE_TRUE(success == TRUE, NS_ERROR_FAILURE);
+ sDBusIsInit = true;
+ }
+
+ DBusError err;
+ dbus_error_init(&err);
+
+ mConnection = already_AddRefed<DBusConnection>(
+ dbus_bus_get_private(DBUS_BUS_SYSTEM, &err));
+
+ if (dbus_error_is_set(&err)) {
+ dbus_error_free(&err);
+ return NS_ERROR_FAILURE;
+ }
+
+ dbus_connection_set_exit_on_disconnect(mConnection, FALSE);
+
+ return NS_OK;
+}
+
+bool RawDBusConnection::Watch()
+{
+ MOZ_ASSERT(MessageLoop::current());
+
+ return NS_SUCCEEDED(DBusWatchConnection(mConnection));
+}
+
+bool RawDBusConnection::Send(DBusMessage* aMessage)
+{
+ MOZ_ASSERT(MessageLoop::current());
+
+ 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(MessageLoop::current());
+
+ auto rv = DBusSendMessageWithReply(mConnection, aCallback, aData, aTimeout,
+ aMessage);
+ if (NS_FAILED(rv)) {
+ return false;
+ }
+
+ 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,
+ ...)
+{
+ va_list args;
+ va_start(args, aFirstArgType);
+
+ auto rv = DBusSendMessageWithReply(mConnection, aCallback, aData,
+ aTimeout, aDestination, aPath, aIntf,
+ aFunc, aFirstArgType, args);
+ va_end(args);
+
+ return NS_SUCCEEDED(rv);
+}
+
+}
+}
diff --git a/ipc/dbus/RawDBusConnection.h b/ipc/dbus/RawDBusConnection.h
new file mode 100644
index 0000000000..21b809edf1
--- /dev/null
+++ b/ipc/dbus/RawDBusConnection.h
@@ -0,0 +1,54 @@
+/* -*- 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_dbus_gonk_rawdbusconnection_h__
+#define mozilla_ipc_dbus_gonk_rawdbusconnection_h__
+
+#include <dbus/dbus.h>
+#include "mozilla/ipc/DBusConnectionRefPtr.h"
+
+namespace mozilla {
+namespace ipc {
+
+typedef void (*DBusReplyCallback)(DBusMessage*, void*);
+
+class RawDBusConnection
+{
+public:
+ RawDBusConnection();
+ virtual ~RawDBusConnection();
+
+ nsresult EstablishDBusConnection();
+
+ bool Watch();
+
+ DBusConnection* GetConnection()
+ {
+ return mConnection;
+ }
+
+ bool Send(DBusMessage* aMessage);
+
+ bool SendWithReply(DBusReplyCallback aCallback, void* aData,
+ int aTimeout, DBusMessage* aMessage);
+
+ bool SendWithReply(DBusReplyCallback aCallback, void* aData,
+ int aTimeout,
+ const char* aDestination,
+ const char* aPath, const char* aIntf,
+ const char *aFunc, int aFirstArgType, ...);
+
+protected:
+ RefPtr<DBusConnection> mConnection;
+
+private:
+ static bool sDBusIsInit;
+};
+
+}
+}
+
+#endif
diff --git a/ipc/dbus/moz.build b/ipc/dbus/moz.build
new file mode 100644
index 0000000000..8df36ea676
--- /dev/null
+++ b/ipc/dbus/moz.build
@@ -0,0 +1,33 @@
+# -*- Mode: python; 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 += [
+ 'DBusConnectionDelete.h',
+ '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'
+
+if CONFIG['MOZ_ENABLE_DBUS']:
+ CFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
+ CFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']
+ CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
+ CXXFLAGS += CONFIG['MOZ_DBUS_GLIB_CFLAGS']