diff options
| -rw-r--r-- | UnityCore/Variant.cpp | 14 | ||||
| -rw-r--r-- | UnityCore/Variant.h | 2 | ||||
| -rw-r--r-- | dash/DashController.cpp | 7 | ||||
| -rw-r--r-- | dash/DashController.h | 1 | ||||
| -rw-r--r-- | dash/DashView.cpp | 3 | ||||
| -rwxr-xr-x | dash/PlacesGroup.cpp | 2 | ||||
| -rw-r--r-- | dash/ResultViewGrid.cpp | 2 | ||||
| -rw-r--r-- | launcher/ApplicationLauncherIcon.cpp | 1 | ||||
| -rw-r--r-- | launcher/LauncherController.cpp | 3 | ||||
| -rw-r--r-- | launcher/LauncherIcon.cpp | 5 | ||||
| -rw-r--r-- | launcher/QuicklistManager.cpp | 5 | ||||
| -rw-r--r-- | launcher/QuicklistView.cpp | 10 | ||||
| -rw-r--r-- | launcher/SimpleLauncherIcon.cpp | 5 | ||||
| -rw-r--r-- | launcher/Tooltip.cpp | 5 | ||||
| -rw-r--r-- | plugins/unityshell/src/UnityGestureTarget.cpp | 6 | ||||
| -rw-r--r-- | plugins/unityshell/src/unity-root-accessible.cpp | 4 | ||||
| -rw-r--r-- | plugins/unityshell/src/unityshell.cpp | 1 | ||||
| -rw-r--r-- | tests/CMakeLists.txt | 5 | ||||
| -rw-r--r-- | tests/test_ubus.cpp | 159 | ||||
| -rw-r--r-- | unity-shared/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | unity-shared/UBusServer.cpp | 129 | ||||
| -rw-r--r-- | unity-shared/UBusServer.h | 73 | ||||
| -rw-r--r-- | unity-shared/UBusWrapper.cpp | 64 | ||||
| -rw-r--r-- | unity-shared/UBusWrapper.h | 35 |
24 files changed, 453 insertions, 90 deletions
diff --git a/UnityCore/Variant.cpp b/UnityCore/Variant.cpp index 21507d001..e8eba40a2 100644 --- a/UnityCore/Variant.cpp +++ b/UnityCore/Variant.cpp @@ -31,7 +31,7 @@ Variant::Variant() Variant::Variant(GVariant* variant) : variant_(variant) { - g_variant_ref_sink(variant_); + if (variant) g_variant_ref_sink(variant_); } Variant::Variant(GVariant* variant, StealRef const& ref) @@ -95,6 +95,11 @@ bool Variant::ASVToHints(HintsMap& hints) const return true; } +void Variant::swap(Variant& other) +{ + std::swap(this->variant_, other.variant_); +} + Variant& Variant::operator=(GVariant* val) { if (variant_) g_variant_unref(variant_); @@ -103,6 +108,13 @@ Variant& Variant::operator=(GVariant* val) return *this; } +Variant& Variant::operator=(Variant other) +{ + swap(other); + + return *this; +} + Variant::operator GVariant* () const { return variant_; diff --git a/UnityCore/Variant.h b/UnityCore/Variant.h index a851a060d..1dcebd38d 100644 --- a/UnityCore/Variant.h +++ b/UnityCore/Variant.h @@ -53,7 +53,9 @@ public: bool ASVToHints(HintsMap& hints) const; + void swap(Variant&); Variant& operator=(GVariant*); + Variant& operator=(Variant); operator GVariant*() const; operator bool() const; diff --git a/dash/DashController.cpp b/dash/DashController.cpp index 38faea260..326b1474b 100644 --- a/dash/DashController.cpp +++ b/dash/DashController.cpp @@ -137,7 +137,7 @@ void Controller::SetupDashView() window_->UpdateInputWindowGeometry(); - ubus_manager_.UnregisterInterest(UBUS_PLACE_ENTRY_ACTIVATE_REQUEST); + ubus_manager_.UnregisterInterest(place_entry_request_id_); } void Controller::RegisterUBusInterests() @@ -146,8 +146,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 39d2abcf7..330f4cfa7 100644 --- a/dash/DashView.cpp +++ b/dash/DashView.cpp @@ -829,7 +829,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 43031695e..f3ea717c6 100755 --- a/dash/PlacesGroup.cpp +++ b/dash/PlacesGroup.cpp @@ -31,7 +31,7 @@ #include <UnityCore/GLibWrapper.h> #include "unity-shared/StaticCairoText.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 c2757410a..bf3ba604f 100644 --- a/dash/ResultViewGrid.cpp +++ b/dash/ResultViewGrid.cpp @@ -31,7 +31,7 @@ #include <UnityCore/Variant.h> #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/ApplicationLauncherIcon.cpp b/launcher/ApplicationLauncherIcon.cpp index 448b4a85b..1afe1767e 100644 --- a/launcher/ApplicationLauncherIcon.cpp +++ b/launcher/ApplicationLauncherIcon.cpp @@ -33,7 +33,6 @@ #include "Launcher.h" #include "MultiMonitor.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 b64884493..13999ec6f 100644 --- a/launcher/LauncherController.cpp +++ b/launcher/LauncherController.cpp @@ -951,7 +951,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 3188654c2..54cc20ac3 100644 --- a/launcher/LauncherIcon.cpp +++ b/launcher/LauncherIcon.cpp @@ -44,7 +44,7 @@ #include "MultiMonitor.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> @@ -865,8 +865,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 b3cc3528d..078bda0e0 100644 --- a/launcher/QuicklistView.cpp +++ b/launcher/QuicklistView.cpp @@ -42,7 +42,7 @@ #include "unity-shared/Introspectable.h" #include "unity-shared/UnitySettings.h" -#include "unity-shared/ubus-server.h" +#include "unity-shared/UBusWrapper.h" #include "unity-shared/UBusMessages.h" #include "unity-shared/DashStyle.h" @@ -281,18 +281,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 3102388d6..1bcffcb08 100644 --- a/launcher/SimpleLauncherIcon.cpp +++ b/launcher/SimpleLauncherIcon.cpp @@ -27,7 +27,7 @@ #include "SimpleLauncherIcon.h" -#include "unity-shared/ubus-server.h" +#include "unity-shared/UBusWrapper.h" #include "unity-shared/UBusMessages.h" namespace unity @@ -92,8 +92,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 9c0f0a7d9..0c4bb6ab1 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 <unity-shared/UnitySettings.h> @@ -103,8 +103,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 37d5c741d..bacbb08c3 100644 --- a/plugins/unityshell/src/unityshell.cpp +++ b/plugins/unityshell/src/unityshell.cpp @@ -59,6 +59,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 d4fe3b703..9d8337bf5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -149,6 +149,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 @@ -168,6 +169,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 ${CMAKE_SOURCE_DIR}/unity-shared/StandaloneWindowManager.cpp @@ -356,6 +359,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 @@ -364,7 +368,6 @@ if (GTEST_SRC_DIR AND ${CMAKE_SOURCE_DIR}/unity-shared/UserThumbnailProvider.cpp ${CMAKE_SOURCE_DIR}/unity-shared/WindowManager.cpp ${CMAKE_SOURCE_DIR}/unity-shared/XKeyboardUtil.cpp - ${CMAKE_SOURCE_DIR}/unity-shared/ubus-server.cpp ${CMAKE_SOURCE_DIR}/plugins/unityshell/src/WindowMinimizeSpeedController.cpp ) target_link_libraries(test-gtest gtest gmock unity-shared ${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 6676fb759..d1bd61857 100644 --- a/unity-shared/CMakeLists.txt +++ b/unity-shared/CMakeLists.txt @@ -56,6 +56,7 @@ set (UNITY_SHARED_SOURCES TextureThumbnailProvider.cpp ThumbnailGenerator.cpp Timer.cpp + UBusServer.cpp UBusWrapper.cpp UScreen.cpp UnitySettings.cpp @@ -65,7 +66,6 @@ set (UNITY_SHARED_SOURCES WindowManager.cpp XKeyboardUtil.cpp XWindowManager.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_; }; } |
