summaryrefslogtreecommitdiff
diff options
-rw-r--r--dash/DashController.cpp7
-rw-r--r--dash/DashController.h1
-rw-r--r--dash/DashView.cpp3
-rwxr-xr-xdash/PlacesGroup.cpp2
-rw-r--r--dash/ResultViewGrid.cpp2
-rw-r--r--launcher/BamfLauncherIcon.cpp1
-rw-r--r--launcher/LauncherController.cpp3
-rw-r--r--launcher/LauncherIcon.cpp5
-rw-r--r--launcher/QuicklistManager.cpp5
-rw-r--r--launcher/QuicklistView.cpp10
-rw-r--r--launcher/SimpleLauncherIcon.cpp5
-rw-r--r--launcher/Tooltip.cpp5
-rw-r--r--plugins/unityshell/src/UnityGestureTarget.cpp6
-rw-r--r--plugins/unityshell/src/unity-root-accessible.cpp4
-rw-r--r--plugins/unityshell/src/unityshell.cpp1
-rw-r--r--tests/CMakeLists.txt5
-rw-r--r--tests/test_ubus.cpp159
-rw-r--r--unity-shared/CMakeLists.txt2
-rw-r--r--unity-shared/UBusServer.cpp129
-rw-r--r--unity-shared/UBusServer.h73
-rw-r--r--unity-shared/UBusWrapper.cpp64
-rw-r--r--unity-shared/UBusWrapper.h35
22 files changed, 438 insertions, 89 deletions
diff --git a/dash/DashController.cpp b/dash/DashController.cpp
index 668a73b1e..1d8ef19aa 100644
--- a/dash/DashController.cpp
+++ b/dash/DashController.cpp
@@ -135,7 +135,7 @@ void Controller::SetupDashView()
window_->UpdateInputWindowGeometry();
- ubus_manager_.UnregisterInterest(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST);
+ ubus_manager_.UnregisterInterest(place_entry_request_id_);
}
void Controller::RegisterUBusInterests()
@@ -144,8 +144,9 @@ void Controller::RegisterUBusInterests()
sigc::mem_fun(this, &Controller::OnExternalShowDash));
ubus_manager_.RegisterInterest(UBUS_PLACE_VIEW_CLOSE_REQUEST,
sigc::mem_fun(this, &Controller::OnExternalHideDash));
- ubus_manager_.RegisterInterest(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST,
- sigc::mem_fun(this, &Controller::OnActivateRequest));
+ place_entry_request_id_ =
+ ubus_manager_.RegisterInterest(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST,
+ sigc::mem_fun(this, &Controller::OnActivateRequest));
ubus_manager_.RegisterInterest(UBUS_DASH_ABOUT_TO_SHOW,
[&] (GVariant*) { EnsureDash(); });
ubus_manager_.RegisterInterest(UBUS_OVERLAY_SHOWN, [&] (GVariant *data)
diff --git a/dash/DashController.h b/dash/DashController.h
index 821b8b96c..0d84db268 100644
--- a/dash/DashController.h
+++ b/dash/DashController.h
@@ -108,6 +108,7 @@ private:
Animator timeline_animator_;
UBusManager ubus_manager_;
unsigned int dbus_owner_;
+ unsigned place_entry_request_id_;
glib::Object<GCancellable> dbus_connect_cancellable_;
static GDBusInterfaceVTable interface_vtable;
};
diff --git a/dash/DashView.cpp b/dash/DashView.cpp
index 21a2a3b72..7ca3d29bb 100644
--- a/dash/DashView.cpp
+++ b/dash/DashView.cpp
@@ -788,7 +788,8 @@ void DashView::OnActivateRequest(GVariant* args)
}
else if (/* visible_ && */ handled_type == NOT_HANDLED)
{
- ubus_manager_.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST);
+ ubus_manager_.SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST, NULL,
+ glib::Source::Priority::HIGH);
}
else if (/* visible_ && */ handled_type == GOTO_DASH_URI)
{
diff --git a/dash/PlacesGroup.cpp b/dash/PlacesGroup.cpp
index f920bd1c2..3ea8f57f8 100755
--- a/dash/PlacesGroup.cpp
+++ b/dash/PlacesGroup.cpp
@@ -33,7 +33,7 @@
#include "unity-shared/StaticCairoText.h"
#include "unity-shared/DashStyle.h"
#include "unity-shared/LineSeparator.h"
-#include "unity-shared/ubus-server.h"
+#include "unity-shared/UBusWrapper.h"
#include "unity-shared/UBusMessages.h"
diff --git a/dash/ResultViewGrid.cpp b/dash/ResultViewGrid.cpp
index 840455f0c..87360d78c 100644
--- a/dash/ResultViewGrid.cpp
+++ b/dash/ResultViewGrid.cpp
@@ -30,7 +30,7 @@
#include "unity-shared/IntrospectableWrappers.h"
#include "unity-shared/Timer.h"
-#include "unity-shared/ubus-server.h"
+#include "unity-shared/UBusWrapper.h"
#include "unity-shared/UBusMessages.h"
#include "ResultViewGrid.h"
#include "math.h"
diff --git a/launcher/BamfLauncherIcon.cpp b/launcher/BamfLauncherIcon.cpp
index ccfac5a32..ae41554b8 100644
--- a/launcher/BamfLauncherIcon.cpp
+++ b/launcher/BamfLauncherIcon.cpp
@@ -34,7 +34,6 @@
#include "MultiMonitor.h"
#include "unity-shared/WindowManager.h"
#include "unity-shared/UBusMessages.h"
-#include "unity-shared/ubus-server.h"
#include <glib/gi18n-lib.h>
#include <gio/gdesktopappinfo.h>
diff --git a/launcher/LauncherController.cpp b/launcher/LauncherController.cpp
index cc17fc610..ed20c2b82 100644
--- a/launcher/LauncherController.cpp
+++ b/launcher/LauncherController.cpp
@@ -945,7 +945,8 @@ void Controller::Impl::SetupIcons()
void Controller::Impl::SendHomeActivationRequest()
{
- ubus.SendMessage(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST, g_variant_new("(sus)", "home.lens", dash::NOT_HANDLED, ""));
+ ubus.SendMessage(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST,
+ g_variant_new("(sus)", "home.lens", dash::NOT_HANDLED, ""));
}
Controller::Controller()
diff --git a/launcher/LauncherIcon.cpp b/launcher/LauncherIcon.cpp
index 5ddd5494f..8dd83aa7c 100644
--- a/launcher/LauncherIcon.cpp
+++ b/launcher/LauncherIcon.cpp
@@ -45,7 +45,7 @@
#include "MultiMonitor.h"
#include "unity-shared/WindowManager.h"
-#include "unity-shared/ubus-server.h"
+#include "unity-shared/UBusWrapper.h"
#include "unity-shared/UBusMessages.h"
#include <UnityCore/GLibWrapper.h>
#include <UnityCore/Variant.h>
@@ -861,8 +861,7 @@ LauncherIcon::SetQuirk(LauncherIcon::Quirk quirk, bool value)
Present(0.5f, 1500);
}
- UBusServer* ubus = ubus_server_get_default();
- ubus_server_send_message(ubus, UBUS_LAUNCHER_ICON_URGENT_CHANGED, g_variant_new_boolean(value));
+ UBusManager::SendMessage(UBUS_LAUNCHER_ICON_URGENT_CHANGED, g_variant_new_boolean(value));
}
if (quirk == Quirk::VISIBLE)
diff --git a/launcher/QuicklistManager.cpp b/launcher/QuicklistManager.cpp
index bdfb51fd3..9f69abb2e 100644
--- a/launcher/QuicklistManager.cpp
+++ b/launcher/QuicklistManager.cpp
@@ -25,7 +25,7 @@
#include "QuicklistView.h"
#include "QuicklistManager.h"
-#include "unity-shared/ubus-server.h"
+#include "unity-shared/UBusWrapper.h"
#include "unity-shared/UBusMessages.h"
namespace unity
@@ -109,8 +109,7 @@ void QuicklistManager::RecvShowQuicklist(nux::BaseWindow* window)
_current_quicklist = quicklist;
quicklist_opened.emit(quicklist);
- UBusServer* ubus = ubus_server_get_default();
- ubus_server_send_message(ubus, UBUS_QUICKLIST_SHOWN, NULL);
+ UBusManager::SendMessage(UBUS_QUICKLIST_SHOWN);
}
void QuicklistManager::RecvHideQuicklist(nux::BaseWindow* window)
diff --git a/launcher/QuicklistView.cpp b/launcher/QuicklistView.cpp
index 1e9996421..77e5aed2b 100644
--- a/launcher/QuicklistView.cpp
+++ b/launcher/QuicklistView.cpp
@@ -41,7 +41,7 @@
#include "unity-shared/Introspectable.h"
-#include "unity-shared/ubus-server.h"
+#include "unity-shared/UBusWrapper.h"
#include "unity-shared/UBusMessages.h"
namespace unity
@@ -282,18 +282,14 @@ QuicklistView::RecvKeyPressed(unsigned long eventType,
case NUX_KP_LEFT:
Hide();
// inform Launcher we switch back to Launcher key-nav
- ubus_server_send_message(ubus_server_get_default(),
- UBUS_QUICKLIST_END_KEY_NAV,
- NULL);
+ UBusManager::SendMessage(UBUS_QUICKLIST_END_KEY_NAV);
break;
// esc (close quicklist, exit key-nav)
case NUX_VK_ESCAPE:
Hide();
// inform UnityScreen we leave key-nav completely
- ubus_server_send_message(ubus_server_get_default(),
- UBUS_LAUNCHER_END_KEY_NAV,
- NULL);
+ UBusManager::SendMessage(UBUS_LAUNCHER_END_KEY_NAV);
break;
// <SPACE>, <RETURN> (activate selected menu-item)
diff --git a/launcher/SimpleLauncherIcon.cpp b/launcher/SimpleLauncherIcon.cpp
index a3c6ccac4..73f66e350 100644
--- a/launcher/SimpleLauncherIcon.cpp
+++ b/launcher/SimpleLauncherIcon.cpp
@@ -28,7 +28,7 @@
#include "SimpleLauncherIcon.h"
#include "unity-shared/PluginAdapter.h"
-#include "unity-shared/ubus-server.h"
+#include "unity-shared/UBusWrapper.h"
#include "unity-shared/UBusMessages.h"
namespace unity
@@ -93,8 +93,7 @@ void SimpleLauncherIcon::OnMouseLeave(int monitor)
void SimpleLauncherIcon::ActivateLauncherIcon(ActionArg arg)
{
activate.emit();
- ubus_server_send_message(ubus_server_get_default(),
- UBUS_PLACE_VIEW_CLOSE_REQUEST,
+ UBusManager::SendMessage(UBUS_PLACE_VIEW_CLOSE_REQUEST,
g_variant_new_boolean(FALSE));
}
diff --git a/launcher/Tooltip.cpp b/launcher/Tooltip.cpp
index 324f2a714..eaf56fb8b 100644
--- a/launcher/Tooltip.cpp
+++ b/launcher/Tooltip.cpp
@@ -24,7 +24,7 @@
#include <UnityCore/Variant.h>
#include "unity-shared/CairoTexture.h"
-#include "unity-shared/ubus-server.h"
+#include "unity-shared/UBusWrapper.h"
#include "unity-shared/UBusMessages.h"
#include "Tooltip.h"
@@ -105,8 +105,7 @@ void Tooltip::ShowTooltipWithTipAt(int anchor_tip_x, int anchor_tip_y)
PushToFront();
ShowWindow(true);
- UBusServer* ubus = ubus_server_get_default();
- ubus_server_send_message(ubus, UBUS_TOOLTIP_SHOWN, NULL);
+ UBusManager::SendMessage(UBUS_TOOLTIP_SHOWN);
}
void Tooltip::Draw(nux::GraphicsEngine& gfxContext, bool forceDraw)
diff --git a/plugins/unityshell/src/UnityGestureTarget.cpp b/plugins/unityshell/src/UnityGestureTarget.cpp
index 3c4ff2ab6..68fe707fb 100644
--- a/plugins/unityshell/src/UnityGestureTarget.cpp
+++ b/plugins/unityshell/src/UnityGestureTarget.cpp
@@ -27,7 +27,7 @@
#include "Launcher.h"
#include "UBusMessages.h"
-#include "ubus-server.h"
+#include "UBusWrapper.h"
using namespace nux;
@@ -46,9 +46,7 @@ GestureDeliveryRequest UnityGestureTarget::GestureEvent(const nux::GestureEvent
else if (event.GetGestureClasses() == TAP_GESTURE
&& event.type == EVENT_GESTURE_END)
{
- ubus_server_send_message(ubus_server_get_default(),
- UBUS_DASH_EXTERNAL_ACTIVATION,
- NULL);
+ UBusManager::SendMessage(UBUS_DASH_EXTERNAL_ACTIVATION);
}
return GestureDeliveryRequest::NONE;
diff --git a/plugins/unityshell/src/unity-root-accessible.cpp b/plugins/unityshell/src/unity-root-accessible.cpp
index 681d676d6..77ad352bc 100644
--- a/plugins/unityshell/src/unity-root-accessible.cpp
+++ b/plugins/unityshell/src/unity-root-accessible.cpp
@@ -30,6 +30,8 @@
#include "nux-base-window-accessible.h"
#include "unitya11y.h"
+#include <UnityCore/Variant.h>
+
#include "UBusWrapper.h"
#include "UBusMessages.h"
@@ -352,7 +354,7 @@ search_for_launcher_window(UnityRootAccessible* self)
}
static void
-ubus_launcher_register_interest_cb(GVariant* variant,
+ubus_launcher_register_interest_cb(unity::glib::Variant const& variant,
UnityRootAccessible* self)
{
//launcher window is the same during all the life of Unity
diff --git a/plugins/unityshell/src/unityshell.cpp b/plugins/unityshell/src/unityshell.cpp
index 610caef1a..6e4dfc5e1 100644
--- a/plugins/unityshell/src/unityshell.cpp
+++ b/plugins/unityshell/src/unityshell.cpp
@@ -58,6 +58,7 @@
#include "unitya11y.h"
#include "UBusMessages.h"
+#include "UBusWrapper.h"
#include "UScreen.h"
#include "config.h"
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 459281ee5..c907c082c 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -147,6 +147,7 @@ if (GTEST_SRC_DIR AND
test_shortcut_model.cpp
test_shortcut_private.cpp
test_showdesktop_handler.cpp
+ test_ubus.cpp
test_unityshell_private.cpp
${CMAKE_CURRENT_BINARY_DIR}/test_glib_signals_utils_marshal.cpp
${CMAKE_SOURCE_DIR}/launcher/AbstractLauncherIcon.cpp
@@ -166,6 +167,8 @@ if (GTEST_SRC_DIR AND
${CMAKE_SOURCE_DIR}/unity-shared/Introspectable.cpp
${CMAKE_SOURCE_DIR}/unity-shared/TextureCache.cpp
${CMAKE_SOURCE_DIR}/unity-shared/Timer.cpp
+ ${CMAKE_SOURCE_DIR}/unity-shared/UBusServer.cpp
+ ${CMAKE_SOURCE_DIR}/unity-shared/UBusWrapper.cpp
${UNITY_SRC}/UnityshellPrivate.cpp
${CMAKE_SOURCE_DIR}/unity-shared/WindowManager.cpp
${UNITY_SRC}/UnityShowdesktopHandler.cpp
@@ -348,6 +351,7 @@ if (GTEST_SRC_DIR AND
${CMAKE_SOURCE_DIR}/unity-shared/Timer.cpp
${CMAKE_SOURCE_DIR}/unity-shared/TextureThumbnailProvider.cpp
${CMAKE_SOURCE_DIR}/unity-shared/ThumbnailGenerator.cpp
+ ${CMAKE_SOURCE_DIR}/unity-shared/UBusServer.cpp
${CMAKE_SOURCE_DIR}/unity-shared/UBusWrapper.cpp
${CMAKE_SOURCE_DIR}/unity-shared/UScreen.cpp
${CMAKE_SOURCE_DIR}/unity-shared/UnitySettings.cpp
@@ -355,7 +359,6 @@ if (GTEST_SRC_DIR AND
${CMAKE_SOURCE_DIR}/unity-shared/UnityWindowView.cpp
${CMAKE_SOURCE_DIR}/unity-shared/UserThumbnailProvider.cpp
${CMAKE_SOURCE_DIR}/unity-shared/WindowManager.cpp
- ${CMAKE_SOURCE_DIR}/unity-shared/ubus-server.cpp
${CMAKE_SOURCE_DIR}/plugins/unityshell/src/WindowMinimizeSpeedController.cpp
)
target_link_libraries(test-gtest gtest gmock ${LIBS})
diff --git a/tests/test_ubus.cpp b/tests/test_ubus.cpp
new file mode 100644
index 000000000..afc45a45a
--- /dev/null
+++ b/tests/test_ubus.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * version 3 along with this program. If not, see
+ * <http://www.gnu.org/licenses/>
+ *
+ * Authored by: Michal Hruby <michal.hruby@canonical.com>
+ *
+ */
+
+#include <gtest/gtest.h>
+#include <time.h>
+#include "TimeUtil.h"
+#include "test_utils.h"
+
+#include <UnityCore/Variant.h>
+#include <UnityCore/GLibSource.h>
+#include "UBusServer.h"
+#include "UBusWrapper.h"
+
+#define MESSAGE1 "TEST MESSAGE ONE"
+#define MESSAGE2 "ՄᕅᏆⲤꙨႧΈ Ϊટ ಗשׁຣ໐ɱË‼‼❢"
+
+using namespace unity;
+
+namespace
+{
+
+struct TestUBusServer : public testing::Test
+{
+ UBusServer ubus_server;
+ bool callback_called;
+ unsigned callback_call_count;
+ glib::Variant last_msg_variant;
+
+ virtual void SetUp()
+ {
+ callback_called = false;
+ callback_call_count = 0;
+ }
+
+ void Callback(glib::Variant const& message)
+ {
+ callback_called = true;
+ callback_call_count++;
+
+ last_msg_variant = message;
+ }
+
+ void ProcessMessages()
+ {
+ bool expired = false;
+ glib::Idle idle([&] { expired = true; return false; },
+ glib::Source::Priority::LOW);
+ Utils::WaitUntil(expired);
+ }
+};
+
+// UBus tests
+
+TEST_F(TestUBusServer, Contruct)
+{
+ EXPECT_FALSE(callback_called);
+}
+
+TEST_F(TestUBusServer, SingleDispatch)
+{
+ ubus_server.RegisterInterest(MESSAGE1, sigc::mem_fun(this, &TestUBusServer::Callback));
+ ubus_server.SendMessage(MESSAGE1);
+
+ ProcessMessages();
+
+ EXPECT_TRUE(callback_called);
+ EXPECT_EQ(callback_call_count, 1);
+}
+
+TEST_F(TestUBusServer, SingleDispatchWithData)
+{
+ ubus_server.RegisterInterest(MESSAGE1, sigc::mem_fun(this, &TestUBusServer::Callback));
+ ubus_server.SendMessage(MESSAGE1, g_variant_new_string("UserData"));
+
+ ProcessMessages();
+
+ EXPECT_TRUE(callback_called);
+ EXPECT_EQ(callback_call_count, 1);
+ EXPECT_EQ(last_msg_variant.GetString(), "UserData");
+}
+
+TEST_F(TestUBusServer, SingleDispatchUnicode)
+{
+ ubus_server.RegisterInterest(MESSAGE2, sigc::mem_fun(this, &TestUBusServer::Callback));
+ ubus_server.SendMessage(MESSAGE2);
+
+ ProcessMessages();
+
+ EXPECT_TRUE(callback_called);
+ EXPECT_EQ(callback_call_count, 1);
+}
+
+TEST_F(TestUBusServer, SendUnregisteredMessage)
+{
+ ubus_server.SendMessage(MESSAGE1);
+
+ ProcessMessages();
+ EXPECT_FALSE(callback_called);
+}
+
+TEST_F(TestUBusServer, SendUninterestedMessage)
+{
+ ubus_server.RegisterInterest(MESSAGE1, sigc::mem_fun(this, &TestUBusServer::Callback));
+ ubus_server.SendMessage(MESSAGE2);
+
+ ProcessMessages();
+ EXPECT_FALSE(callback_called);
+}
+
+TEST_F(TestUBusServer, MultipleDispatches)
+{
+ ubus_server.RegisterInterest(MESSAGE1, sigc::mem_fun(this, &TestUBusServer::Callback));
+ ubus_server.RegisterInterest(MESSAGE1, sigc::mem_fun(this, &TestUBusServer::Callback));
+ ubus_server.RegisterInterest(MESSAGE1, sigc::mem_fun(this, &TestUBusServer::Callback));
+ ubus_server.SendMessage(MESSAGE1);
+
+ ProcessMessages();
+ EXPECT_TRUE(callback_called);
+ EXPECT_EQ(callback_call_count, 3);
+}
+
+TEST_F(TestUBusServer, MultipleDispatchesWithData)
+{
+ int cb_count = 0;
+ ubus_server.RegisterInterest(MESSAGE1, [&cb_count] (glib::Variant const& data)
+ {
+ cb_count++;
+ EXPECT_EQ(data.GetString(), "foo");
+ });
+ ubus_server.RegisterInterest(MESSAGE1, [&cb_count] (glib::Variant const& data)
+ {
+ cb_count++;
+ EXPECT_EQ(data.GetString(), "foo");
+ });
+ ubus_server.SendMessage(MESSAGE2);
+ ubus_server.SendMessage(MESSAGE1, g_variant_new_string("foo"));
+
+ ProcessMessages();
+ EXPECT_EQ(cb_count, 2);
+}
+
+}
diff --git a/unity-shared/CMakeLists.txt b/unity-shared/CMakeLists.txt
index c2c5b9562..fcfe2811e 100644
--- a/unity-shared/CMakeLists.txt
+++ b/unity-shared/CMakeLists.txt
@@ -57,6 +57,7 @@ set (UNITY_SHARED_SOURCES
TextureThumbnailProvider.cpp
ThumbnailGenerator.cpp
Timer.cpp
+ UBusServer.cpp
UBusWrapper.cpp
UScreen.cpp
UnitySettings.cpp
@@ -64,7 +65,6 @@ set (UNITY_SHARED_SOURCES
UnityWindowView.cpp
UserThumbnailProvider.cpp
WindowManager.cpp
- ubus-server.cpp
)
add_library (unity-shared STATIC ${UNITY_SHARED_SOURCES})
diff --git a/unity-shared/UBusServer.cpp b/unity-shared/UBusServer.cpp
new file mode 100644
index 000000000..47d0262f0
--- /dev/null
+++ b/unity-shared/UBusServer.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2012 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Michal Hruby <michal.hruby@canonical.com>
+ */
+
+#include <boost/lexical_cast.hpp>
+#include <NuxCore/Logger.h>
+
+#include "UBusServer.h"
+
+namespace unity
+{
+
+namespace
+{
+nux::logging::Logger logger("unity.ubus");
+}
+
+UBusServer::UBusServer()
+ : last_id_(0)
+{}
+
+UBusServer::~UBusServer()
+{
+}
+
+unsigned UBusServer::RegisterInterest(std::string const& interest_name,
+ UBusCallback const& slot)
+{
+ if (!slot || interest_name.empty())
+ return 0;
+
+ unsigned connection_id = ++last_id_;
+ auto connection = std::make_shared<UBusConnection>(slot, connection_id);
+ interests_.insert(std::pair<std::string, UBusConnection::Ptr>(interest_name, connection));
+
+ return connection_id;
+}
+
+void UBusServer::UnregisterInterest(unsigned connection_id)
+{
+ for (auto it = interests_.begin(); it != interests_.end(); ++it)
+ {
+ if ((*it).second->id == connection_id)
+ {
+ interests_.erase(it);
+ return;
+ }
+ }
+}
+
+void UBusServer::SendMessage(std::string const& message_name,
+ glib::Variant const& args)
+{
+ SendMessageFull(message_name, args, glib::Source::Priority::DEFAULT_IDLE);
+}
+
+void UBusServer::SendMessageFull(std::string const& message_name,
+ glib::Variant const& args,
+ glib::Source::Priority prio)
+{
+ // queue the message
+ msg_queue_.insert(std::pair<int, std::pair<std::string, glib::Variant>>(prio, std::pair<std::string, glib::Variant>(message_name, args)));
+
+ // start the source (if not already running)
+ auto src_nick = boost::lexical_cast<std::string>(static_cast<int>(prio));
+ auto src_ptr = source_manager_.GetSource(src_nick);
+ if (!src_ptr)
+ {
+ source_manager_.Add(new glib::Idle([this, prio] ()
+ {
+ return DispatchMessages(prio);
+ }, prio));
+ }
+}
+
+bool UBusServer::DispatchMessages(glib::Source::Priority prio)
+{
+ // copy messages we are about to dispatch to a separate container
+ std::vector<std::pair<std::string, glib::Variant> > dispatched_msgs;
+
+ auto iterators = msg_queue_.equal_range(prio);
+ for (auto it = iterators.first; it != iterators.second; ++it)
+ {
+ dispatched_msgs.push_back((*it).second);
+ }
+
+ // remove the messages from the queue
+ msg_queue_.erase(prio);
+
+ for (unsigned i = 0; i < dispatched_msgs.size(); i++)
+ {
+ // invoke callbacks for this message_name
+ std::string const& message_name = dispatched_msgs[i].first;
+ glib::Variant const& msg_args = dispatched_msgs[i].second;
+ auto interest_it = interests_.find(message_name);
+ while (interest_it != interests_.end())
+ {
+ // add a reference to make sure we don't crash if the slot unregisters itself
+ UBusConnection::Ptr connection((*interest_it).second);
+ interest_it++;
+ // invoke the slot
+ // FIXME: what if this slot unregisters the next? We should mark the interests map dirty in UnregisterInterest
+ connection->slot(msg_args);
+
+ if (interest_it == interests_.end() ||
+ (*interest_it).first != message_name)
+ break;
+ }
+ }
+
+ // return true if there are new queued messages with this prio
+ return msg_queue_.find(prio) != msg_queue_.end();
+}
+
+}
diff --git a/unity-shared/UBusServer.h b/unity-shared/UBusServer.h
new file mode 100644
index 000000000..948ab2c9e
--- /dev/null
+++ b/unity-shared/UBusServer.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 Canonical Ltd
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ */
+
+#ifndef UNITY_UBUS_SERVER_H
+#define UNITY_UBUS_SERVER_H
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <boost/utility.hpp>
+#include <map>
+
+#include <UnityCore/Variant.h>
+#include <UnityCore/GLibSource.h>
+
+namespace unity
+{
+
+typedef std::function<void(glib::Variant const&)> UBusCallback;
+
+class UBusServer : public boost::noncopyable
+{
+public:
+ UBusServer();
+ ~UBusServer();
+
+ unsigned RegisterInterest(std::string const& interest_name,
+ UBusCallback const& slot);
+ void UnregisterInterest(unsigned connection_id);
+ void SendMessage(std::string const& message_name,
+ glib::Variant const& args = glib::Variant());
+ void SendMessageFull(std::string const& message_name,
+ glib::Variant const& args,
+ glib::Source::Priority prio);
+
+private:
+ struct UBusConnection
+ {
+ typedef std::shared_ptr<UBusConnection> Ptr;
+
+ UBusCallback slot;
+ unsigned id;
+
+ UBusConnection(UBusCallback const& cb, unsigned connection_id)
+ : slot(cb), id(connection_id) {}
+ };
+
+ bool DispatchMessages(glib::Source::Priority);
+
+ unsigned last_id_;
+ std::multimap<std::string, UBusConnection::Ptr> interests_;
+ std::multimap<int, std::pair<std::string, glib::Variant> > msg_queue_;
+ glib::SourceManager source_manager_;
+};
+
+}
+
+#endif
diff --git a/unity-shared/UBusWrapper.cpp b/unity-shared/UBusWrapper.cpp
index e1f280092..9935d77e5 100644
--- a/unity-shared/UBusWrapper.cpp
+++ b/unity-shared/UBusWrapper.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Canonical Ltd
+ * Copyright (C) 2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -13,65 +13,59 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
- * Authored by: Neil Jagdish Patel <neil.patel@canonical.com>
+ * Authored by: Michal Hruby <michal.hruby@canonical.com>
*/
+#include <boost/lexical_cast.hpp>
+#include <NuxCore/Logger.h>
+
#include "UBusWrapper.h"
namespace unity
{
+// initialize the global static ptr
+std::unique_ptr<UBusServer> UBusManager::server(new UBusServer());
+
UBusManager::UBusManager()
- : server_(ubus_server_get_default())
-{}
+{
+}
UBusManager::~UBusManager()
{
- for (auto connection: connections_)
+ // we don't want to modify a container while iterating it
+ std::set<unsigned> ids_copy(connection_ids_);
+ for (auto it = ids_copy.begin(); it != ids_copy.end(); ++it)
{
- ubus_server_unregister_interest(server_, connection->id);
+ UnregisterInterest(*it);
}
}
-void UBusManager::RegisterInterest(std::string const& interest_name,
- UBusManagerCallback slot)
+unsigned UBusManager::RegisterInterest(std::string const& interest_name,
+ UBusCallback const& slot)
{
- if (!slot || interest_name.empty())
- return;
+ unsigned c_id = server->RegisterInterest(interest_name, slot);
+
+ if (c_id != 0) connection_ids_.insert(c_id);
- auto connection = std::make_shared<UBusConnection>();
- connection->name = interest_name;
- connection->slot = slot;
- connection->id = ubus_server_register_interest(server_,
- interest_name.c_str(),
- UBusManager::OnCallback,
- connection.get());
- connections_.push_back(connection);
+ return c_id;
}
-void UBusManager::UnregisterInterest(std::string const& interest_name)
+void UBusManager::UnregisterInterest(unsigned connection_id)
{
- for (auto it = connections_.begin(); it != connections_.end(); ++it)
+ auto it = connection_ids_.find(connection_id);
+ if (it != connection_ids_.end())
{
- if ((*it)->name == interest_name)
- {
- ubus_server_unregister_interest(server_, (*it)->id);
- connections_.erase(it);
- break;
- }
+ server->UnregisterInterest(connection_id);
+ connection_ids_.erase(it);
}
}
-void UBusManager::OnCallback(GVariant* args, gpointer user_data)
-{
- UBusConnection* connection = static_cast<UBusConnection*>(user_data);
-
- connection->slot(args);
-}
-
-void UBusManager::SendMessage(std::string const& message_name, GVariant* args)
+void UBusManager::SendMessage(std::string const& message_name,
+ glib::Variant const& args,
+ glib::Source::Priority prio)
{
- ubus_server_send_message(server_, message_name.c_str(), args);
+ server->SendMessageFull(message_name, args, prio);
}
}
diff --git a/unity-shared/UBusWrapper.h b/unity-shared/UBusWrapper.h
index c18ff0a79..f3646237b 100644
--- a/unity-shared/UBusWrapper.h
+++ b/unity-shared/UBusWrapper.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Canonical Ltd
+ * Copyright (C) 2010-2012 Canonical Ltd
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
@@ -23,8 +23,13 @@
#include <string>
#include <vector>
#include <boost/utility.hpp>
+#include <map>
+#include <set>
-#include "ubus-server.h"
+#include <UnityCore/Variant.h>
+#include <UnityCore/GLibSource.h>
+
+#include "UBusServer.h"
namespace unity
{
@@ -32,29 +37,19 @@ namespace unity
class UBusManager : public boost::noncopyable
{
public:
- typedef std::function<void(GVariant*)> UBusManagerCallback;
-
UBusManager();
~UBusManager();
- void RegisterInterest(std::string const& interest_name, UBusManagerCallback slot);
- void UnregisterInterest(std::string const& interest_name);
- void SendMessage(std::string const& message_name, GVariant* args = NULL);
+ unsigned RegisterInterest(std::string const& interest_name,
+ UBusCallback const& slot);
+ void UnregisterInterest(unsigned connection_id);
+ static void SendMessage(std::string const& message_name,
+ glib::Variant const& args = glib::Variant(),
+ glib::Source::Priority prio = glib::Source::Priority::DEFAULT);
private:
- struct UBusConnection
- {
- typedef std::shared_ptr<UBusConnection> Ptr;
-
- std::string name;
- UBusManagerCallback slot;
- guint id;
- };
-
- static void OnCallback(GVariant* args, gpointer user_data);
-
- UBusServer* server_;
- std::vector<UBusConnection::Ptr> connections_;
+ static std::unique_ptr<UBusServer> server;
+ std::set<unsigned> connection_ids_;
};
}