diff -Nru hud-13.10.1+14.04.20140314/debian/changelog hud-13.10.1+14.04.20140326/debian/changelog --- hud-13.10.1+14.04.20140314/debian/changelog 2014-03-27 18:06:13.000000000 +0000 +++ hud-13.10.1+14.04.20140326/debian/changelog 2014-03-27 18:06:13.000000000 +0000 @@ -1,3 +1,37 @@ +hud (13.10.1+14.04.20140326-0ubuntu1) trusty; urgency=low + + [ Pete Woods ] + * Add safety valve for DBusMenuCollector that also reports the + offending application (LP: #1280372) + + -- Ubuntu daily release Wed, 26 Mar 2014 09:36:22 +0000 + +hud (13.10.1+14.04.20140325-0ubuntu1) trusty; urgency=low + + [ Charles Kerr ] + * Simplify the implementation of QtGActionGroup. This started off with + the intent of removing the overhead of g_action_group_list_actions() + in QtGActionGroup::Action(), but then I found + QtGActionGroup::Action() was only called in the object's constructor + and destructor, so it made more sense to remove the function + altogether. Summary of changes:   * Plugged GVariant leak in + QtGActionGroup::TriggerAction()   * Plugged char* leak in + QtGMenuUtils::makeStringListQVariant   * ActionGroup ctor calls + g_action_group_list_actions() once instead of n+1 times   * + ActionGroup dtor calls g_action_group_list_actions() once instead of + n times   * Removed unused public method Size()   * Removed newly- + unused public method Action()   * Removed newly-unused field m_size + (LP: #1296746) + + [ Pete Woods ] + * Add null guards to ItemStore search (LP: #1292237) + * Fix test failures exposed by fix to libqtdbustest (LP: #1296744) + * Call only "safe" write method from UNIX signal handler See + http://pubs.opengroup.org/onlinepubs/000095399/functions/xsh_chap02_ + 04.html#tag_02_04_01 (LP: #1296602) + + -- Ubuntu daily release Tue, 25 Mar 2014 12:46:25 +0000 + hud (13.10.1+14.04.20140314-0ubuntu1) trusty; urgency=low [ Pete Woods ] diff -Nru hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGActionGroup.cpp hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGActionGroup.cpp --- hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGActionGroup.cpp 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGActionGroup.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -27,22 +27,16 @@ { ConnectCallbacks(); - gchar** actions_list = g_action_group_list_actions( m_action_group ); + auto actions_list = g_action_group_list_actions( m_action_group ); if( actions_list ) { - while( actions_list[m_size] != nullptr ) + for( int i = 0; actions_list[i]; ++i ) { - ++m_size; + emit ActionAdded( actions_list[i] ); } g_strfreev( actions_list ); } - - // add initial items - for( int i = 0; i < m_size; ++i ) - { - emit ActionAdded( Action( i ) ); - } } QtGActionGroup::~QtGActionGroup() @@ -52,9 +46,15 @@ return; } - for( int i = 0; i < m_size; ++i ) + auto actions_list = g_action_group_list_actions( m_action_group ); + if( actions_list ) { - emit ActionRemoved( Action( i ) ); + for( int i = 0; actions_list[i]; ++i ) + { + emit ActionRemoved( actions_list[i] ); + } + + g_strfreev( actions_list ); } DisconnectCallbacks(); @@ -70,74 +70,67 @@ return m_action_group; } -int QtGActionGroup::Size() const -{ - return m_size; -} - -QString QtGActionGroup::Action( int index ) -{ - if( index >= m_size ) - { - return QString(); - } - - QString action_name; - gchar** actions_list = g_action_group_list_actions( m_action_group ); - - action_name = QString( actions_list[index] ); - - g_strfreev( actions_list ); - - return action_name; -} - void QtGActionGroup::TriggerAction( QString action_name, bool checked ) { - QString prefix = action_name.left( action_name.indexOf( '.' ) ); + QPair split = QtGMenuUtils::splitPrefixAndName(action_name); + const QString& prefix(split.first); + if( prefix != m_action_prefix ) { return; } - action_name = action_name.right( action_name.size() - action_name.indexOf( '.' ) - 1 ); - std::string action = action_name.toStdString(); + const QString& action(split.second); + QByteArray action_utf = action.toUtf8(); const GVariantType* type = g_action_group_get_action_parameter_type( m_action_group, - action.c_str() ); + action_utf.constData() ); if( type == nullptr ) { - g_action_group_activate_action( m_action_group, action.c_str(), nullptr ); + g_action_group_activate_action( m_action_group, action_utf.constData(), nullptr ); } else { ///! need to evaluate and send parameter value if( g_variant_type_equal( type, G_VARIANT_TYPE_STRING ) ) { - GVariant* param = g_variant_new_string( action.c_str() ); - g_action_group_activate_action( m_action_group, action.c_str(), param ); + GVariant* param = g_variant_new_string( action_utf.constData() ); + g_action_group_activate_action( m_action_group, action_utf.constData(), param ); + g_variant_unref( param ); } } } +QString QtGActionGroup::FullName( const QString& prefix, const QString& action_name ) +{ + if ( prefix.isEmpty() ) + { + return action_name; + } + else + { + return prefix + "." + action_name; + } +} + void QtGActionGroup::EmitStates() { - gchar** actions_list = g_action_group_list_actions( m_action_group ); + auto actions_list = g_action_group_list_actions( m_action_group ); - for( int i = 0; i < m_size; ++i ) + for( int i = 0; actions_list && actions_list[i]; ++i ) { gchar* action_name = actions_list[i]; bool enabled = G_ACTION_GROUP_GET_IFACE( m_action_group ) ->get_action_enabled( m_action_group, action_name ); if( !enabled ) - emit ActionEnabled( m_action_prefix + "." + action_name, enabled ); + emit ActionEnabled( FullName(m_action_prefix, action_name), enabled ); const GVariantType* type = g_action_group_get_action_parameter_type( m_action_group, action_name ); if( type != nullptr ) - emit ActionParameterized( m_action_prefix + "." + action_name, type != nullptr ); + emit ActionParameterized( FullName(m_action_prefix, action_name), type != nullptr ); } g_strfreev( actions_list ); @@ -152,14 +145,12 @@ bool enabled = G_ACTION_GROUP_GET_IFACE( self->m_action_group ) ->get_action_enabled( self->m_action_group, action_name ); if( !enabled ) - emit self->ActionEnabled( self->m_action_prefix + "." + action_name, enabled ); + emit self->ActionEnabled( FullName(self->m_action_prefix, action_name), enabled ); const GVariantType* type = g_action_group_get_action_parameter_type( self->m_action_group, action_name ); if( type != nullptr ) - emit self->ActionParameterized( self->m_action_prefix + "." + action_name, type != nullptr ); - - ++self->m_size; + emit self->ActionParameterized( FullName(self->m_action_prefix, action_name), type != nullptr ); } void QtGActionGroup::ActionRemovedCallback( GActionGroup* action_group, gchar* action_name, @@ -167,15 +158,13 @@ { QtGActionGroup* self = reinterpret_cast< QtGActionGroup* >( user_data ); emit self->ActionRemoved( action_name ); - - --self->m_size; } void QtGActionGroup::ActionEnabledCallback( GActionGroup* action_group, gchar* action_name, gboolean enabled, gpointer user_data ) { QtGActionGroup* self = reinterpret_cast< QtGActionGroup* >( user_data ); - emit self->ActionEnabled( self->m_action_prefix + "." + action_name, enabled ); + emit self->ActionEnabled( FullName(self->m_action_prefix, action_name), enabled ); } void QtGActionGroup::ActionStateChangedCallback( GActionGroup* action_group, gchar* action_name, diff -Nru hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGActionGroup.h hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGActionGroup.h --- hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGActionGroup.h 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGActionGroup.h 2014-03-26 09:35:50.000000000 +0000 @@ -37,9 +37,6 @@ virtual ~QtGActionGroup(); GActionGroup* ActionGroup() const; - int Size() const; - - QString Action( int index ); Q_SIGNALS: void ActionAdded( QString action_name ); @@ -53,6 +50,7 @@ void EmitStates(); private: + static QString FullName( const QString& prefix, const QString& name ); static void ActionAddedCallback( GActionGroup* action_group, gchar* action_name, gpointer user_data ); static void ActionRemovedCallback( GActionGroup* action_group, gchar* action_name, @@ -66,7 +64,6 @@ void DisconnectCallbacks(); private: - int m_size = 0; QString m_action_prefix; GActionGroup* m_action_group = nullptr; diff -Nru hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuImporterPrivate.cpp hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuImporterPrivate.cpp --- hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuImporterPrivate.cpp 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuImporterPrivate.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -31,7 +31,7 @@ QDBusServiceWatcher::WatchForOwnerChange ), m_parent( parent ), m_connection( g_bus_get_sync( G_BUS_TYPE_SESSION, NULL, NULL ) ), - m_service( service.toStdString() ), + m_service( service ), m_menu_path( menu_path ), m_action_paths( action_paths ) { @@ -162,8 +162,8 @@ QString menu_path = m_menu_path.path(); m_menu_model = std::make_shared< QtGMenuModel > ( - G_MENU_MODEL( g_dbus_menu_model_get( m_connection, m_service.c_str(), menu_path.toUtf8().constData() ) ), - m_service.c_str(), menu_path.toUtf8().constData() ); + G_MENU_MODEL( g_dbus_menu_model_get( m_connection, m_service.toUtf8().constData(), menu_path.toUtf8().constData() ) ), + m_service, menu_path, m_action_paths ); connect( m_menu_model.get(), SIGNAL( MenuItemsChanged( QtGMenuModel*, int, int, int ) ), &m_parent, SIGNAL( MenuItemsChanged()) ); @@ -174,12 +174,15 @@ // clear the action groups for the refresh ClearActionGroups(); - for( auto const& action_path_it : m_action_paths.toStdMap() ) + QMapIterator action_path_it(m_action_paths); + while( action_path_it.hasNext() ) { - QString action_path = action_path_it.second.path(); + action_path_it.next(); + + QString action_path = action_path_it.value().path(); m_action_groups.push_back( - std::make_shared< QtGActionGroup > ( action_path_it.first, - G_ACTION_GROUP( g_dbus_action_group_get( m_connection, m_service.c_str(), action_path.toUtf8().constData() ) ) ) ); + std::make_shared< QtGActionGroup > ( action_path_it.key(), + G_ACTION_GROUP( g_dbus_action_group_get( m_connection, m_service.toUtf8().constData(), action_path.toUtf8().constData() ) ) ) ); auto action_group = m_action_groups.back(); diff -Nru hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuImporterPrivate.h hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuImporterPrivate.h --- hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuImporterPrivate.h 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuImporterPrivate.h 2014-03-26 09:35:50.000000000 +0000 @@ -69,7 +69,7 @@ QtGMenuImporter& m_parent; GDBusConnection* m_connection; - std::string m_service; + QString m_service; QDBusObjectPath m_menu_path; QMap m_action_paths; diff -Nru hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuModel.cpp hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuModel.cpp --- hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuModel.cpp 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuModel.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -18,6 +18,7 @@ #include #include +#include using namespace qtgmenu; @@ -26,11 +27,12 @@ { } -QtGMenuModel::QtGMenuModel( GMenuModel* model, const QString& bus_name, const QString& menu_path ) +QtGMenuModel::QtGMenuModel( GMenuModel* model, const QString& bus_name, const QString& menu_path, const QMap& action_paths ) : QtGMenuModel( model, LinkType::Root, nullptr, 0 ) { m_bus_name = bus_name; m_menu_path = menu_path; + m_action_paths = action_paths; } QtGMenuModel::QtGMenuModel( GMenuModel* model, LinkType link_type, QtGMenuModel* parent, int index ) @@ -46,6 +48,7 @@ m_bus_name = m_parent->m_bus_name; m_menu_path = m_parent->m_menu_path; + m_action_paths = m_parent->m_action_paths; gchar* label = NULL; if( g_menu_model_get_item_attribute( m_parent->m_model, index, @@ -59,15 +62,13 @@ } gchar* action_name = NULL; + QString qaction_name; if( g_menu_model_get_item_attribute( m_parent->m_model, index, G_MENU_ATTRIBUTE_ACTION, "s", &action_name ) ) { - QString qaction_name = QString::fromUtf8( action_name ); + qaction_name = QString::fromUtf8( action_name ); g_free( action_name ); - int name_length = qaction_name.size() - qaction_name.indexOf( '.' ) - 1; - qaction_name = qaction_name.right( name_length ); - m_ext_menu->menuAction()->setProperty( c_property_actionName, qaction_name ); } @@ -84,6 +85,16 @@ // dbus paths m_ext_menu->menuAction()->setProperty( c_property_busName, m_bus_name ); m_ext_menu->menuAction()->setProperty( c_property_menuPath, m_menu_path ); + + if( !qaction_name.isEmpty() ) + { + QPair split = QtGMenuUtils::splitPrefixAndName(qaction_name); + const QString& prefix(split.first); + if( m_action_paths.contains(prefix) ) + { + m_ext_menu->menuAction()->setProperty( c_property_actionsPath, m_action_paths[prefix].path() ); + } + } } } diff -Nru hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuModel.h hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuModel.h --- hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuModel.h 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuModel.h 2014-03-26 09:35:50.000000000 +0000 @@ -19,6 +19,7 @@ #ifndef QTGMENUMODEL_H #define QTGMENUMODEL_H +#include #include #include #include @@ -43,7 +44,7 @@ }; explicit QtGMenuModel( GMenuModel* model ); - QtGMenuModel( GMenuModel* model, const QString& bus_name, const QString& menu_path ); + QtGMenuModel( GMenuModel* model, const QString& bus_name, const QString& menu_path, const QMap& action_paths ); virtual ~QtGMenuModel(); GMenuModel* Model() const; @@ -59,6 +60,7 @@ constexpr static const char* c_property_actionName = "actionName"; constexpr static const char* c_property_isParameterized = "isParameterized"; constexpr static const char* c_property_busName = "busName"; + constexpr static const char* c_property_actionsPath = "actionsPath"; constexpr static const char* c_property_menuPath = "menuPath"; constexpr static const char* c_property_keywords = "keywords"; constexpr static const char* c_property_hud_toolbar_item = "hud-toolbar-item"; @@ -113,6 +115,7 @@ QString m_bus_name; QString m_menu_path; + QMap m_action_paths; std::map< QString, QAction* > m_actions; }; diff -Nru hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuUtils.cpp hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuUtils.cpp --- hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuUtils.cpp 2014-03-14 16:36:51.000000000 +0000 +++ hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuUtils.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -92,6 +92,8 @@ while( stringArray[i] != NULL ) value << QString::fromUtf8( stringArray[i++] ); + g_free (const_cast(stringArray)); + return QVariant::fromValue( value ); } @@ -227,3 +229,17 @@ return QKeySequence::fromString( shortcut ); } + +QPair QtGMenuUtils::splitPrefixAndName( const QString& name ) +{ + int index = name.indexOf( '.' ); + + if( index == -1 ) + { + return qMakePair(QString(), name); + } + else + { + return qMakePair(name.left( index ), name.right( name.size() - index - 1 )); + } +} diff -Nru hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuUtils.h hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuUtils.h --- hud-13.10.1+14.04.20140314/libqtgmenu/internal/QtGMenuUtils.h 2014-03-14 16:36:51.000000000 +0000 +++ hud-13.10.1+14.04.20140326/libqtgmenu/internal/QtGMenuUtils.h 2014-03-26 09:35:50.000000000 +0000 @@ -19,6 +19,8 @@ #ifndef QTGMENUUTILS_H #define QTGMENUUTILS_H +#include + class _GVariant; typedef _GVariant GVariant; @@ -34,6 +36,7 @@ public: static QVariant GVariantToQVariant( GVariant* gvariant ); static QKeySequence QStringToQKeySequence( QString& shortcut ); + static QPair splitPrefixAndName( const QString& name ); }; } // namespace qtgmenu diff -Nru hud-13.10.1+14.04.20140314/service/CMakeLists.txt hud-13.10.1+14.04.20140326/service/CMakeLists.txt --- hud-13.10.1+14.04.20140314/service/CMakeLists.txt 2014-03-14 16:36:51.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/CMakeLists.txt 2014-03-26 09:35:50.000000000 +0000 @@ -29,6 +29,7 @@ QueryImpl.cpp Result.cpp SearchSettings.cpp + SignalHandler.cpp SqliteUsageTracker.cpp UsageTracker.cpp Voice.cpp diff -Nru hud-13.10.1+14.04.20140314/service/DBusMenuCollector.cpp hud-13.10.1+14.04.20140326/service/DBusMenuCollector.cpp --- hud-13.10.1+14.04.20140314/service/DBusMenuCollector.cpp 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/DBusMenuCollector.cpp 2014-03-26 09:36:14.000000000 +0000 @@ -89,11 +89,17 @@ return hash; } -void DBusMenuCollector::openMenu(QMenu *menu) { +void DBusMenuCollector::openMenu(QMenu *menu, unsigned int &limit) { if (!menu) { return; } + if (limit == 0) { + qWarning() << "Hit DBusMenu safety valve for menu at" << m_service + << m_path.path(); + return; + } + menu->aboutToShow(); for (int i(0); m_menuImporter && i < menu->actions().size(); ++i) { @@ -107,17 +113,25 @@ QMenu *child(action->menu()); if (child) { - openMenu(child); + --limit; + openMenu(child, limit); } } } -void DBusMenuCollector::hideMenu(QMenu *menu) { +void DBusMenuCollector::hideMenu(QMenu *menu, unsigned int &limit) { + if (limit == 0) { + qWarning() << "Hit DBusMenu safety valve for menu at" << m_service + << m_path.path(); + return; + } + for (int i(0); i < menu->actions().size(); ++i) { QAction *action = menu->actions().at(i); QMenu *child(action->menu()); if (child) { - hideMenu(child); + --limit; + hideMenu(child, limit); } } @@ -136,7 +150,8 @@ } if (collectorToken.isNull()) { - openMenu(m_menuImporter->menu()); + unsigned int limit(50); + openMenu(m_menuImporter->menu(), limit); if(m_menuImporter.isNull()) { return QList(); @@ -154,7 +169,8 @@ if(m_menuImporter.isNull()) { return; } - hideMenu(m_menuImporter->menu()); + unsigned int limit(50); + hideMenu(m_menuImporter->menu(), limit); } void DBusMenuCollector::WindowRegistered(uint windowId, const QString &service, diff -Nru hud-13.10.1+14.04.20140314/service/DBusMenuCollector.h hud-13.10.1+14.04.20140326/service/DBusMenuCollector.h --- hud-13.10.1+14.04.20140314/service/DBusMenuCollector.h 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/DBusMenuCollector.h 2014-03-26 09:36:14.000000000 +0000 @@ -60,9 +60,9 @@ const QDBusObjectPath &menuObjectPath); protected: - void openMenu(QMenu *menu); + void openMenu(QMenu *menu, unsigned int &limit); - void hideMenu(QMenu *menu); + void hideMenu(QMenu *menu, unsigned int &limit); unsigned int m_windowId; diff -Nru hud-13.10.1+14.04.20140314/service/ItemStore.cpp hud-13.10.1+14.04.20140326/service/ItemStore.cpp --- hud-13.10.1+14.04.20140314/service/ItemStore.cpp 2014-03-14 16:37:11.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/ItemStore.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -31,7 +31,7 @@ static const QRegularExpression SINGLE_AMPERSAND("(? tempResults; for (auto it(m_items.constBegin()); it != m_items.constEnd(); ++it) { - tempResults.insertMulti(m_usageTracker->usage(m_applicationId, - convertToEntry(it.value(), it.value()->action())), it.key()); + const QAction* action = it.value()->action(); + if (action) { + tempResults.insertMulti( + m_usageTracker->usage(m_applicationId, + convertToEntry(it.value(), action)), it.key()); + } } int maxResults = std::min(m_items.size(), 20); @@ -214,6 +218,10 @@ Item::Ptr item(m_items[id]); const QAction *action(item->action()); + if (!action) { + return; + } + QString commandName(convertActionText(action)); Result::HighlightList commandHighlights; @@ -271,7 +279,7 @@ } QString ItemStore::executeParameterized(unsigned long long commandId, - QString &baseAction, QDBusObjectPath &actionPath, + QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath) { Item::Ptr item(m_items[commandId]); @@ -289,7 +297,15 @@ return QString(); } - baseAction = action->property("actionName").toString(); + QString name = action->property("actionName").toString(); + int index = name.indexOf( '.' ); + if (index == -1) { + baseAction = name; + } else { + prefix = name.left(index); + baseAction = name.right(name.size() - index - 1); + } + actionPath = QDBusObjectPath(action->property("actionsPath").toString()); modelPath = QDBusObjectPath(action->property("menuPath").toString()); diff -Nru hud-13.10.1+14.04.20140314/service/ItemStore.h hud-13.10.1+14.04.20140326/service/ItemStore.h --- hud-13.10.1+14.04.20140314/service/ItemStore.h 2014-03-14 16:37:00.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/ItemStore.h 2014-03-26 09:35:50.000000000 +0000 @@ -57,7 +57,7 @@ void execute(unsigned long long commandId); QString executeParameterized(unsigned long long commandId, - QString &baseAction, QDBusObjectPath &actionPath, + QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath); void executeToolbar(const QString &item); diff -Nru hud-13.10.1+14.04.20140314/service/main.cpp hud-13.10.1+14.04.20140326/service/main.cpp --- hud-13.10.1+14.04.20140314/service/main.cpp 2014-03-14 16:36:51.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/main.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -18,19 +18,14 @@ #include #include +#include #include #include -#include using namespace std; using namespace hud::service; -static void exitQt(int sig) { - Q_UNUSED(sig); - QApplication::exit(0); -} - int main(int argc, char *argv[]) { qputenv("QT_QPA_PLATFORM", "minimal"); QApplication application(argc, argv); @@ -39,12 +34,11 @@ bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR); textdomain(GETTEXT_PACKAGE); - signal(SIGINT, &exitQt); - signal(SIGTERM, &exitQt); - try { Factory factory; factory.singletonHudService(); + SignalHandler handler; + handler.setupUnixSignalHandlers(); return application.exec(); } catch (std::exception &e) { qWarning() << _("Hud Service:") << e.what(); diff -Nru hud-13.10.1+14.04.20140314/service/QueryImpl.cpp hud-13.10.1+14.04.20140326/service/QueryImpl.cpp --- hud-13.10.1+14.04.20140314/service/QueryImpl.cpp 2014-03-14 16:37:00.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/QueryImpl.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -162,9 +162,8 @@ } qulonglong commandId(item.variant().toULongLong()); - prefix = "hud"; modelSection = 1; - return m_windowToken->executeParameterized(commandId, baseAction, + return m_windowToken->executeParameterized(commandId, prefix, baseAction, actionPath, modelPath); } diff -Nru hud-13.10.1+14.04.20140314/service/SignalHandler.cpp hud-13.10.1+14.04.20140326/service/SignalHandler.cpp --- hud-13.10.1+14.04.20140314/service/SignalHandler.cpp 1970-01-01 00:00:00.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/SignalHandler.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2014 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 along + * with this program. If not, see . + * + * Author: Pete Woods + */ + +#include + +#include +#include + +#include +#include +#include + +using namespace hud::service; + +int SignalHandler::sigintFd[2]; + +int SignalHandler::sigtermFd[2]; + +SignalHandler::SignalHandler(QObject *parent) : + QObject(parent) { + + if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigintFd)) { + qFatal("Couldn't create INT socketpair"); + } + if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigtermFd)) { + qFatal("Couldn't create TERM socketpair"); + } + + m_socketNotifierInt = new QSocketNotifier(sigintFd[1], QSocketNotifier::Read, this); + connect(m_socketNotifierInt, &QSocketNotifier::activated, this, &SignalHandler::handleSigInt); + m_socketNotifierTerm = new QSocketNotifier(sigtermFd[1], QSocketNotifier::Read, this); + connect(m_socketNotifierTerm, &QSocketNotifier::activated, this, &SignalHandler::handleSigTerm); +} + +void SignalHandler::intSignalHandler(int) { + char a = 1; + ::write(sigintFd[0], &a, sizeof(a)); +} + +void SignalHandler::termSignalHandler(int) { + char a = 1; + ::write(sigtermFd[0], &a, sizeof(a)); +} + +int SignalHandler::setupUnixSignalHandlers() { + struct sigaction sigint, sigterm; + + sigint.sa_handler = SignalHandler::intSignalHandler; + sigemptyset(&sigint.sa_mask); + sigint.sa_flags = 0; + sigint.sa_flags |= SA_RESTART; + + if (sigaction(SIGINT, &sigint, 0) > 0) + return 1; + + sigterm.sa_handler = SignalHandler::termSignalHandler; + sigemptyset(&sigterm.sa_mask); + sigterm.sa_flags |= SA_RESTART; + + if (sigaction(SIGTERM, &sigterm, 0) > 0) + return 2; + + return 0; +} + +void SignalHandler::handleSigTerm() { + m_socketNotifierTerm->setEnabled(false); + char tmp; + ::read(sigtermFd[1], &tmp, sizeof(tmp)); + + QCoreApplication::exit(0); + + m_socketNotifierTerm->setEnabled(true); +} + +void SignalHandler::handleSigInt() { + m_socketNotifierInt->setEnabled(false); + char tmp; + ::read(sigintFd[1], &tmp, sizeof(tmp)); + + QCoreApplication::exit(0); + + m_socketNotifierInt->setEnabled(true); +} diff -Nru hud-13.10.1+14.04.20140314/service/SignalHandler.h hud-13.10.1+14.04.20140326/service/SignalHandler.h --- hud-13.10.1+14.04.20140314/service/SignalHandler.h 1970-01-01 00:00:00.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/SignalHandler.h 2014-03-26 09:35:50.000000000 +0000 @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2014 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 along + * with this program. If not, see . + * + * Author: Pete Woods + */ + +#ifndef HUD_SERVICE_SIGNALHANDLER_H_ +#define HUD_SERVICE_SIGNALHANDLER_H_ + +#include +#include + +namespace hud { +namespace service { + +class SignalHandler: public QObject { +Q_OBJECT + +public: + SignalHandler(QObject *parent = 0); + + ~SignalHandler() = default; + + static int setupUnixSignalHandlers(); + +protected Q_SLOTS: + void handleSigInt(); + + void handleSigTerm(); + +protected: + static void intSignalHandler(int unused); + + static void termSignalHandler(int unused); + + static int sigintFd[2]; + + static int sigtermFd[2]; + + QSocketNotifier *m_socketNotifierInt; + + QSocketNotifier *m_socketNotifierTerm; +}; + +} +} + +#endif /* HUD_SERVICE_SIGNALHANDLER_H_ */ diff -Nru hud-13.10.1+14.04.20140314/service/Window.h hud-13.10.1+14.04.20140326/service/Window.h --- hud-13.10.1+14.04.20140314/service/Window.h 2014-03-14 16:37:00.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/Window.h 2014-03-26 09:35:50.000000000 +0000 @@ -42,7 +42,7 @@ virtual void execute(unsigned long long commandId) = 0; virtual QString executeParameterized(unsigned long long commandId, - QString &baseAction, QDBusObjectPath &actionPath, + QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath) = 0; virtual void executeToolbar(const QString &item) = 0; diff -Nru hud-13.10.1+14.04.20140314/service/WindowImpl.cpp hud-13.10.1+14.04.20140326/service/WindowImpl.cpp --- hud-13.10.1+14.04.20140314/service/WindowImpl.cpp 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/WindowImpl.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -55,10 +55,10 @@ } QString WindowTokenImpl::executeParameterized(unsigned long long commandId, - QString &baseAction, QDBusObjectPath &actionPath, + QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath) { - return m_items->executeParameterized(commandId, baseAction, actionPath, - modelPath); + return m_items->executeParameterized(commandId, prefix, baseAction, + actionPath, modelPath); } void WindowTokenImpl::executeToolbar(const QString &item) { diff -Nru hud-13.10.1+14.04.20140314/service/WindowImpl.h hud-13.10.1+14.04.20140326/service/WindowImpl.h --- hud-13.10.1+14.04.20140314/service/WindowImpl.h 2014-03-14 16:37:00.000000000 +0000 +++ hud-13.10.1+14.04.20140326/service/WindowImpl.h 2014-03-26 09:35:50.000000000 +0000 @@ -49,7 +49,7 @@ void execute(unsigned long long commandId) override; - QString executeParameterized(unsigned long long commandId, + QString executeParameterized(unsigned long long commandId, QString &prefix, QString &baseAction, QDBusObjectPath &actionPath, QDBusObjectPath &modelPath) override; diff -Nru hud-13.10.1+14.04.20140314/tests/integration/TestHud.cpp hud-13.10.1+14.04.20140326/tests/integration/TestHud.cpp --- hud-13.10.1+14.04.20140314/tests/integration/TestHud.cpp 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/tests/integration/TestHud.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -373,7 +373,7 @@ EXPECT_FALSE(executedSpy.isEmpty()); actionInvokedSpy.wait(); - EXPECT_FALSE(actionInvokedSpy.isEmpty()); + ASSERT_FALSE(actionInvokedSpy.isEmpty()); EXPECT_EQ(QVariantList() << QVariant("close"), actionInvokedSpy.at(0)); } diff -Nru hud-13.10.1+14.04.20140314/tests/menus/test-menu-input-model-shortcuts.c hud-13.10.1+14.04.20140326/tests/menus/test-menu-input-model-shortcuts.c --- hud-13.10.1+14.04.20140314/tests/menus/test-menu-input-model-shortcuts.c 2014-03-14 16:36:51.000000000 +0000 +++ hud-13.10.1+14.04.20140326/tests/menus/test-menu-input-model-shortcuts.c 2014-03-26 09:35:50.000000000 +0000 @@ -45,22 +45,22 @@ GMenu * menu = g_menu_new(); GMenuItem * mi = NULL; - mi = g_menu_item_new("Save", "save"); + mi = g_menu_item_new("Save", "unity.save"); g_menu_item_set_attribute_value(mi, "accel", g_variant_new_string("S")); g_menu_append_item(menu, mi); - mi = g_menu_item_new("Quiter", "quiter"); + mi = g_menu_item_new("Quiter", "unity.quiter"); g_menu_item_set_attribute_value(mi, "accel", g_variant_new_string("Q")); g_menu_append_item(menu, mi); - mi = g_menu_item_new("Close", "close"); + mi = g_menu_item_new("Close", "unity.close"); g_menu_item_set_attribute_value(mi, "accel", g_variant_new_string("W")); g_menu_append_item(menu, mi); - mi = g_menu_item_new("Nothing", "nothing"); + mi = g_menu_item_new("Nothing", "unity.nothing"); g_menu_append_item(menu, mi); GSimpleAction *save = g_simple_action_new("save", NULL); diff -Nru hud-13.10.1+14.04.20140314/tests/unit/qtgmenu/TestQtGMenu.cpp hud-13.10.1+14.04.20140326/tests/unit/qtgmenu/TestQtGMenu.cpp --- hud-13.10.1+14.04.20140314/tests/unit/qtgmenu/TestQtGMenu.cpp 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/tests/unit/qtgmenu/TestQtGMenu.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -40,7 +40,7 @@ protected: TestQtGMenu() - : m_importer( c_service, QDBusObjectPath( c_path ), "", QDBusObjectPath( c_path ) ), + : m_importer( c_service, QDBusObjectPath( c_path ), "app", QDBusObjectPath( c_path ) ), m_items_changed_spy( &m_importer, SIGNAL( MenuItemsChanged() ) ), @@ -376,7 +376,7 @@ m_action_enabled_spy.wait(); EXPECT_FALSE( m_action_enabled_spy.empty() ); - EXPECT_EQ( "new", m_action_enabled_spy.at( 0 ).at( 0 ).toString().toStdString() ); + EXPECT_EQ( "app.new", m_action_enabled_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "false", m_action_enabled_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_enabled_spy.clear(); @@ -384,7 +384,7 @@ m_action_enabled_spy.wait(); EXPECT_FALSE( m_action_enabled_spy.empty() ); - EXPECT_EQ( "new", m_action_enabled_spy.at( 0 ).at( 0 ).toString().toStdString() ); + EXPECT_EQ( "app.new", m_action_enabled_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "true", m_action_enabled_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_enabled_spy.clear(); @@ -519,7 +519,7 @@ file_menu->actions().at( 0 )->trigger(); m_action_activated_spy.wait(); - EXPECT_FALSE( m_action_activated_spy.empty() ); + ASSERT_FALSE( m_action_activated_spy.empty() ); EXPECT_EQ( "new", m_action_activated_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "", m_action_activated_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_activated_spy.clear(); @@ -527,7 +527,7 @@ file_menu->actions().at( 1 )->trigger(); m_action_activated_spy.wait(); - EXPECT_FALSE( m_action_activated_spy.empty() ); + ASSERT_FALSE( m_action_activated_spy.empty() ); EXPECT_EQ( "open", m_action_activated_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "", m_action_activated_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_activated_spy.clear(); @@ -535,7 +535,7 @@ file_menu->actions().at( 3 )->trigger(); m_action_activated_spy.wait(); - EXPECT_FALSE( m_action_activated_spy.empty() ); + ASSERT_FALSE( m_action_activated_spy.empty() ); EXPECT_EQ( "lock", m_action_activated_spy.at( 0 ).at( 0 ).toString().toStdString() ); EXPECT_EQ( "", m_action_activated_spy.at( 0 ).at( 1 ).toString().toStdString() ); m_action_activated_spy.clear(); diff -Nru hud-13.10.1+14.04.20140314/tests/unit/service/Mocks.h hud-13.10.1+14.04.20140326/tests/unit/service/Mocks.h --- hud-13.10.1+14.04.20140314/tests/unit/service/Mocks.h 2014-03-14 16:37:28.000000000 +0000 +++ hud-13.10.1+14.04.20140326/tests/unit/service/Mocks.h 2014-03-26 09:35:50.000000000 +0000 @@ -114,8 +114,8 @@ MOCK_METHOD1(executeToolbar, void(const QString &)); - MOCK_METHOD4(executeParameterized, QString(unsigned long long, - QString &, QDBusObjectPath &, QDBusObjectPath &)); + MOCK_METHOD5(executeParameterized, QString(unsigned long long, + QString &, QString &, QDBusObjectPath &, QDBusObjectPath &)); MOCK_CONST_METHOD0(commands, QList()); diff -Nru hud-13.10.1+14.04.20140314/tests/unit/service/TestItemStore.cpp hud-13.10.1+14.04.20140326/tests/unit/service/TestItemStore.cpp --- hud-13.10.1+14.04.20140314/tests/unit/service/TestItemStore.cpp 2014-03-14 16:37:11.000000000 +0000 +++ hud-13.10.1+14.04.20140326/tests/unit/service/TestItemStore.cpp 2014-03-26 09:35:50.000000000 +0000 @@ -331,4 +331,25 @@ EXPECT_EQ("Can Cherry", search("Ban")); } +TEST_F(TestItemStore, DeletedActions) { + QMenu root; + + QMenu file("&File"); + file.addAction("Apple"); + file.addAction("Banana"); + file.addAction("Can Cherry"); + root.addMenu(&file); + + store->indexMenu(&root); + + file.clear(); + root.clear(); + + // It should not crash! :) + EXPECT_EQ("", search("flibble")); + + // It should not crash! :) + EXPECT_EQ("", search("")); +} + } // namespace