Merge lp:~larryprice/ubuntu-app-launch/no-display-options into lp:ubuntu-app-launch/16.04

Proposed by Larry Price
Status: Merged
Approved by: Ted Gould
Approved revision: 272
Merged at revision: 222
Proposed branch: lp:~larryprice/ubuntu-app-launch/no-display-options
Merge into: lp:ubuntu-app-launch/16.04
Prerequisite: lp:~ted/ubuntu-app-launch/app-object
Diff against target: 239 lines (+136/-22)
2 files modified
libubuntu-app-launch/application-info-desktop.cpp (+59/-1)
tests/application-info-desktop.cpp (+77/-21)
To merge this branch: bzr merge lp:~larryprice/ubuntu-app-launch/no-display-options
Reviewer Review Type Date Requested Status
Ted Gould (community) Approve
Review via email: mp+292857@code.launchpad.net

Commit message

Add additional cases for not presenting desktop launchers based on keyfile entries.

Description of the change

Add additional cases for not presenting desktop launchers based on keyfile entries.

This includes looking for NoDisplay and Hidden, verifying the Type is Application, and checking to see if Unity is included in the "OnlyShowIn" or "NotShowIn" lists. This logic is similar to what we've been using in libertine-container-manager to determine which app launchers to show. The intent is to update the UAL API for use in libertine-scope to reduce duplication of logic in fetching application launchers.

To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote :

Overall, cool, thanks for the fix! Some little things that need to be fixed inline.

review: Needs Fixing
272. By Larry Price

Fix memory management in stringlist method and use XDG_CURRENT_DESKTOP to determine environment (review recycle)

Revision history for this message
Ted Gould (ted) wrote :

Great, thanks!

review: Approve
273. By Larry Price

Merge with trunk 16.04

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'libubuntu-app-launch/application-info-desktop.cpp'
--- libubuntu-app-launch/application-info-desktop.cpp 2016-03-03 20:48:24 +0000
+++ libubuntu-app-launch/application-info-desktop.cpp 2016-04-26 13:49:48 +0000
@@ -18,6 +18,7 @@
18 */18 */
1919
20#include "application-info-desktop.h"20#include "application-info-desktop.h"
21#include <cstdlib>
2122
22namespace ubuntu23namespace ubuntu
23{24{
@@ -25,9 +26,20 @@
25{26{
26namespace app_info27namespace app_info
27{28{
2829namespace
30{
29constexpr const char* DESKTOP_GROUP = "Desktop Entry";31constexpr const char* DESKTOP_GROUP = "Desktop Entry";
3032
33struct TypeTag;
34typedef TypeTagger<TypeTag, std::string> Type;
35
36struct HiddenTag;
37typedef TypeTagger<HiddenTag, bool> Hidden;
38
39struct NoDisplayTag;
40typedef TypeTagger<NoDisplayTag, bool> NoDisplay;
41} // anonymous namespace
42
31template <typename T>43template <typename T>
32auto stringFromKeyfile(std::shared_ptr<GKeyFile> keyfile, const std::string& key, const std::string& exceptionText = {})44auto stringFromKeyfile(std::shared_ptr<GKeyFile> keyfile, const std::string& key, const std::string& exceptionText = {})
33 -> T45 -> T
@@ -113,12 +125,58 @@
113 return retval;125 return retval;
114}126}
115127
128bool stringlistFromKeyfileContains(std::shared_ptr<GKeyFile> keyfile,
129 const gchar* key,
130 const std::string& match,
131 bool defaultValue)
132{
133 GError* error = nullptr;
134 auto results = g_key_file_get_string_list(keyfile.get(), DESKTOP_GROUP, key, nullptr, &error);
135 if (error != nullptr)
136 {
137 g_error_free(error);
138 return defaultValue;
139 }
140
141 bool result = false;
142 for (auto i = 0; results[i] != nullptr; ++i)
143 {
144 if (results[i] == match)
145 {
146 result = true;
147 break;
148 }
149 }
150 g_strfreev(results);
151
152 return result;
153}
154
116Desktop::Desktop(std::shared_ptr<GKeyFile> keyfile, const std::string& basePath)155Desktop::Desktop(std::shared_ptr<GKeyFile> keyfile, const std::string& basePath)
117 : _keyfile([keyfile]() {156 : _keyfile([keyfile]() {
118 if (!keyfile)157 if (!keyfile)
119 {158 {
120 throw std::runtime_error("Can not build a desktop application info object with a null keyfile");159 throw std::runtime_error("Can not build a desktop application info object with a null keyfile");
121 }160 }
161 if (stringFromKeyfile<Type>(keyfile, "Type").value() != "Application")
162 {
163 throw std::runtime_error("Keyfile does not represent application type");
164 }
165 if (boolFromKeyfile<NoDisplay>(keyfile, "NoDisplay", false).value())
166 {
167 throw std::runtime_error("Application is not meant to be displayed");
168 }
169 if (boolFromKeyfile<Hidden>(keyfile, "Hidden", false).value())
170 {
171 throw std::runtime_error("Application keyfile is hidden");
172 }
173 auto xdg_current_desktop = getenv("XDG_CURRENT_DESKTOP");
174 if (stringlistFromKeyfileContains(keyfile, "NotShowIn", xdg_current_desktop, false)
175 || !stringlistFromKeyfileContains(keyfile, "OnlyShowIn", xdg_current_desktop, true))
176 {
177 throw std::runtime_error("Application is not shown in Unity");
178 }
179
122 return keyfile;180 return keyfile;
123 }())181 }())
124 , _basePath(basePath)182 , _basePath(basePath)
125183
=== modified file 'tests/application-info-desktop.cpp'
--- tests/application-info-desktop.cpp 2016-02-10 22:04:00 +0000
+++ tests/application-info-desktop.cpp 2016-04-26 13:49:48 +0000
@@ -20,28 +20,46 @@
20#include "application-info-desktop.h"20#include "application-info-desktop.h"
2121
22#include <gtest/gtest.h>22#include <gtest/gtest.h>
23#include <cstdlib>
24
25namespace
26{
27#define DESKTOP "Desktop Entry"
2328
24class ApplicationInfoDesktop : public ::testing::Test29class ApplicationInfoDesktop : public ::testing::Test
25{30{
31protected:
32 ApplicationInfoDesktop()
33 : test_dekstop_env("SomeFreeDesktop")
34 {
35 }
36
26 virtual void SetUp()37 virtual void SetUp()
27 {38 {
39 setenv("XDG_CURRENT_DESKTOP", test_dekstop_env.c_str(), true);
28 }40 }
2941
30 virtual void TearDown()42 virtual void TearDown()
31 {43 {
32 }44 }
45
46 std::shared_ptr<GKeyFile> defaultKeyfile()
47 {
48 auto keyfile = std::shared_ptr<GKeyFile>(g_key_file_new(), g_key_file_free);
49 g_key_file_set_string(keyfile.get(), DESKTOP, "Type", "Application");
50 g_key_file_set_string(keyfile.get(), DESKTOP, "Name", "Foo App");
51 g_key_file_set_string(keyfile.get(), DESKTOP, "Exec", "foo");
52 g_key_file_set_string(keyfile.get(), DESKTOP, "Icon", "foo.png");
53 return keyfile;
54 }
55
56 const std::string test_dekstop_env;
33};57};
3458
35#define DESKTOP "Desktop Entry"
3659
37TEST_F(ApplicationInfoDesktop, DefaultState)60TEST_F(ApplicationInfoDesktop, DefaultState)
38{61{
39 auto keyfile = std::shared_ptr<GKeyFile>(g_key_file_new(), g_key_file_free);62 auto appinfo = ubuntu::app_launch::app_info::Desktop(defaultKeyfile(), "/");
40 g_key_file_set_string(keyfile.get(), DESKTOP, "Name", "Foo App");
41 g_key_file_set_string(keyfile.get(), DESKTOP, "Exec", "foo");
42 g_key_file_set_string(keyfile.get(), DESKTOP, "Icon", "foo.png");
43
44 auto appinfo = ubuntu::app_launch::app_info::Desktop(keyfile, "/");
4563
46 EXPECT_EQ("Foo App", appinfo.name().value());64 EXPECT_EQ("Foo App", appinfo.name().value());
47 EXPECT_EQ("", appinfo.description().value());65 EXPECT_EQ("", appinfo.description().value());
@@ -66,21 +84,61 @@
6684
67TEST_F(ApplicationInfoDesktop, KeyfileErrors)85TEST_F(ApplicationInfoDesktop, KeyfileErrors)
68{86{
87 // empty
69 EXPECT_THROW(ubuntu::app_launch::app_info::Desktop({}, "/"), std::runtime_error);88 EXPECT_THROW(ubuntu::app_launch::app_info::Desktop({}, "/"), std::runtime_error);
7089
71 auto noname = std::shared_ptr<GKeyFile>(g_key_file_new(), g_key_file_free);90 // empty name
72 g_key_file_set_string(noname.get(), DESKTOP, "Comment", "This is a comment");91 auto noname = defaultKeyfile();
73 g_key_file_set_string(noname.get(), DESKTOP, "Exec", "foo");92 g_key_file_remove_key(noname.get(), DESKTOP, "Name", nullptr);
74 g_key_file_set_string(noname.get(), DESKTOP, "Icon", "foo.png");
75
76 EXPECT_THROW(ubuntu::app_launch::app_info::Desktop(noname, "/"), std::runtime_error);93 EXPECT_THROW(ubuntu::app_launch::app_info::Desktop(noname, "/"), std::runtime_error);
7794
78 auto noicon = std::shared_ptr<GKeyFile>(g_key_file_new(), g_key_file_free);95 // empty icon
79 g_key_file_set_string(noicon.get(), DESKTOP, "Name", "Foo App");96 auto noicon = defaultKeyfile();
80 g_key_file_set_string(noicon.get(), DESKTOP, "Comment", "This is a comment");97 g_key_file_remove_key(noicon.get(), DESKTOP, "Icon", nullptr);
81 g_key_file_set_string(noicon.get(), DESKTOP, "Exec", "foo");
82
83 EXPECT_THROW(ubuntu::app_launch::app_info::Desktop(noicon, "/"), std::runtime_error);98 EXPECT_THROW(ubuntu::app_launch::app_info::Desktop(noicon, "/"), std::runtime_error);
99
100 // wrong type
101 auto wrongtype = defaultKeyfile();
102 g_key_file_set_string(wrongtype.get(), DESKTOP, "Type", "MimeType");
103 EXPECT_THROW(ubuntu::app_launch::app_info::Desktop(wrongtype, "/"), std::runtime_error);
104
105 // not displayable
106 auto nodisplay = defaultKeyfile();
107 g_key_file_set_string(nodisplay.get(), DESKTOP, "NoDisplay", "true");
108 EXPECT_THROW(ubuntu::app_launch::app_info::Desktop(nodisplay, "/"), std::runtime_error);
109
110 // hidden
111 auto hidden = defaultKeyfile();
112 g_key_file_set_string(hidden.get(), DESKTOP, "Hidden", "true");
113 EXPECT_THROW(ubuntu::app_launch::app_info::Desktop(hidden, "/"), std::runtime_error);
114
115 // not shown in Unity
116 auto notshowin = defaultKeyfile();
117 g_key_file_set_string(notshowin.get(), DESKTOP, "NotShowIn", ("Gnome;" + test_dekstop_env + ";").c_str());
118 EXPECT_THROW(ubuntu::app_launch::app_info::Desktop(notshowin, "/"), std::runtime_error);
119
120 // only show in not Unity
121 auto onlyshowin = defaultKeyfile();
122 g_key_file_set_string(onlyshowin.get(), DESKTOP, "OnlyShowIn", "KDE;Gnome;");
123 EXPECT_THROW(ubuntu::app_launch::app_info::Desktop(onlyshowin, "/"), std::runtime_error);
124}
125
126TEST_F(ApplicationInfoDesktop, KeyfileShowListEdgeCases)
127{
128 // Not appearing in not show list
129 auto notshowin = defaultKeyfile();
130 g_key_file_set_string(notshowin.get(), DESKTOP, "NotShowIn", "Gnome;KDE;");
131 EXPECT_NO_THROW(ubuntu::app_launch::app_info::Desktop(notshowin, "/"));
132
133 // Appearing explicitly in only show list
134 auto onlyshowin = defaultKeyfile();
135 g_key_file_set_string(onlyshowin.get(), DESKTOP, "OnlyShowIn", (test_dekstop_env + ";Gnome;").c_str());
136 EXPECT_NO_THROW(ubuntu::app_launch::app_info::Desktop(onlyshowin, "/"));
137
138 // Appearing explicitly in only show list not first
139 auto onlyshowinmiddle = defaultKeyfile();
140 g_key_file_set_string(onlyshowinmiddle.get(), DESKTOP, "OnlyShowIn", ("Gnome;" + test_dekstop_env + ";KDE;").c_str());
141 EXPECT_NO_THROW(ubuntu::app_launch::app_info::Desktop(onlyshowinmiddle, "/"));
84}142}
85143
86TEST_F(ApplicationInfoDesktop, Orientations)144TEST_F(ApplicationInfoDesktop, Orientations)
@@ -97,10 +155,7 @@
97 true155 true
98 };156 };
99157
100 auto keyfile = std::shared_ptr<GKeyFile>(g_key_file_new(), g_key_file_free);158 auto keyfile = defaultKeyfile();
101 g_key_file_set_string(keyfile.get(), DESKTOP, "Name", "Foo App");
102 g_key_file_set_string(keyfile.get(), DESKTOP, "Exec", "foo");
103 g_key_file_set_string(keyfile.get(), DESKTOP, "Icon", "foo.png");
104159
105 EXPECT_EQ(defaultOrientations, ubuntu::app_launch::app_info::Desktop(keyfile, "/").supportedOrientations());160 EXPECT_EQ(defaultOrientations, ubuntu::app_launch::app_info::Desktop(keyfile, "/").supportedOrientations());
106161
@@ -146,3 +201,4 @@
146 EXPECT_EQ(defaultOrientations,201 EXPECT_EQ(defaultOrientations,
147 ubuntu::app_launch::app_info::Desktop(keyfile, "/").supportedOrientations());202 ubuntu::app_launch::app_info::Desktop(keyfile, "/").supportedOrientations());
148}203}
204} //anonymous namespace

Subscribers

People subscribed via source and target branches