diff options
| -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/BamfLauncherIcon.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 | 
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_;  };  } | 
