Merge lp:~ted/ubuntu-app-launch/snappy-backend-no-snap into lp:ubuntu-app-launch/16.10

Proposed by Ted Gould
Status: Superseded
Proposed branch: lp:~ted/ubuntu-app-launch/snappy-backend-no-snap
Merge into: lp:ubuntu-app-launch/16.10
Prerequisite: lp:~ted/ubuntu-app-launch/snappy-backend-list-only
Diff against target: 3651 lines (+1256/-1267)
30 files modified
docs/index.rst (+11/-1)
helpers.c (+13/-6)
helpers.h (+5/-0)
libubuntu-app-launch/CMakeLists.txt (+4/-3)
libubuntu-app-launch/app-info.c (+52/-129)
libubuntu-app-launch/app-info.h (+0/-35)
libubuntu-app-launch/appid.h (+60/-0)
libubuntu-app-launch/application-impl-base.cpp (+285/-32)
libubuntu-app-launch/application-impl-base.h (+34/-9)
libubuntu-app-launch/application-impl-click.cpp (+104/-5)
libubuntu-app-launch/application-impl-click.h (+23/-3)
libubuntu-app-launch/application-impl-legacy.cpp (+136/-22)
libubuntu-app-launch/application-impl-legacy.h (+16/-4)
libubuntu-app-launch/application-impl-libertine.cpp (+104/-6)
libubuntu-app-launch/application-impl-libertine.h (+17/-0)
libubuntu-app-launch/application-info-desktop.cpp (+4/-1)
libubuntu-app-launch/application-info-desktop.h (+20/-2)
libubuntu-app-launch/application.cpp (+171/-51)
libubuntu-app-launch/click-exec.c (+0/-170)
libubuntu-app-launch/click-exec.h (+0/-25)
libubuntu-app-launch/desktop-exec.c (+0/-218)
libubuntu-app-launch/desktop-exec.h (+0/-26)
libubuntu-app-launch/registry.cpp (+1/-1)
libubuntu-app-launch/second-exec-core.c (+43/-41)
libubuntu-app-launch/second-exec-core.h (+5/-1)
libubuntu-app-launch/ubuntu-app-launch-trace.tp (+1/-2)
libubuntu-app-launch/ubuntu-app-launch.cpp (+84/-428)
tests/exec-util-test.cc (+23/-11)
tests/libual-cpp-test.cc (+38/-33)
tests/list-apps.cpp (+2/-2)
To merge this branch: bzr merge lp:~ted/ubuntu-app-launch/snappy-backend-no-snap
Reviewer Review Type Date Requested Status
unity-api-1-bot continuous-integration Needs Fixing
Unity API Team Pending
Review via email: mp+301966@code.launchpad.net

This proposal supersedes a proposal from 2016-08-03.

This proposal has been superseded by a proposal from 2016-08-04.

To post a comment you must log in.
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:352
No commit message was specified in the merge proposal. Click on the following link and set the commit message (if you want a jenkins rebuild you need to trigger it yourself):
https://code.launchpad.net/~ted/ubuntu-app-launch/snappy-backend-no-snap/+merge/301966/+edit-commit-message

https://jenkins.canonical.com/unity-api-1/job/lp-ubuntu-app-launch-ci/18/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/277/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/283
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-1-sourcepkg/release=vivid+overlay/217
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-1-sourcepkg/release=xenial+overlay/217
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-1-sourcepkg/release=yakkety/217
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/146/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/146/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/146/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/146/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/146/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/146/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/146/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/146/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/146/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-ubuntu-app-launch-ci/18/rebuild

review: Needs Fixing (continuous-integration)
353. By Ted Gould

Grab the revisions in the no-find-discover branch

354. By Ted Gould

Pulling through trunk

355. By Ted Gould

Adding comments to the functions

356. By Ted Gould

Adding comments to the functions

357. By Ted Gould

Fix some more comments

358. By Ted Gould

Pull through OOM updates

359. By Ted Gould

Fix legacy instance pull through

360. By Ted Gould

Updating to trunk

361. By Ted Gould

Bring in updates to no-find-discover branch

362. By Ted Gould

Fix abicheck

363. By Ted Gould

Write text explaining the app id schemes for the various backends

364. By Ted Gould

Use empty instead of checking the size

365. By Ted Gould

Going full auto

366. By Ted Gould

Removing a string cast

367. By Ted Gould

Spelling fix

368. By Ted Gould

Make sure we don't copy the tools structures

369. By Ted Gould

Grab changes and Jenkins fixes

370. By Ted Gould

Getting some list bus love

371. By Ted Gould

Merging trunk

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'docs/index.rst'
2--- docs/index.rst 2016-04-29 14:20:11 +0000
3+++ docs/index.rst 2016-08-04 14:02:19 +0000
4@@ -109,7 +109,7 @@
5 Application Icon Finder
6 ------------------------
7
8-.. doxygenclass:: ubuntu::app_launch::app_info::IconFinder
9+.. doxygenclass:: ubuntu::app_launch::IconFinder
10 :project: libubuntu-app-launch
11 :members:
12 :protected-members:
13@@ -146,6 +146,16 @@
14 :private-members:
15 :undoc-members:
16
17+Upstart Instance
18+----------------
19+
20+.. doxygenclass:: ubuntu::app_launch::app_impls::UpstartInstance
21+ :project: libubuntu-app-launch
22+ :members:
23+ :protected-members:
24+ :private-members:
25+ :undoc-members:
26+
27 Quality
28 =======
29
30
31=== modified file 'helpers.c'
32--- helpers.c 2016-08-04 14:02:18 +0000
33+++ helpers.c 2016-08-04 14:02:19 +0000
34@@ -490,7 +490,7 @@
35 GDBusConnection * con;
36 GMainLoop * mainloop;
37 guint signal_subscribe;
38- guint timeout;
39+ GSource * timeout;
40 };
41
42 static gboolean
43@@ -498,7 +498,7 @@
44 {
45 handshake_t * handshake = (handshake_t *)user_data;
46 g_main_loop_quit(handshake->mainloop);
47- handshake->timeout = 0;
48+ handshake->timeout = NULL;
49 return G_SOURCE_REMOVE;
50 }
51
52@@ -508,7 +508,9 @@
53 GError * error = NULL;
54 handshake_t * handshake = g_new0(handshake_t, 1);
55
56- handshake->mainloop = g_main_loop_new(NULL, FALSE);
57+ GMainContext * context = g_main_context_get_thread_default();
58+
59+ handshake->mainloop = g_main_loop_new(context, FALSE);
60 handshake->con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
61
62 if (error != NULL) {
63@@ -539,7 +541,9 @@
64 &error);
65
66 /* Really, Unity? */
67- handshake->timeout = g_timeout_add_seconds(1, unity_too_slow_cb, handshake);
68+ handshake->timeout = g_timeout_source_new_seconds(1);
69+ g_source_set_callback(handshake->timeout, unity_too_slow_cb, handshake, NULL);
70+ g_source_attach(handshake->timeout, context);
71
72 return handshake;
73 }
74@@ -552,8 +556,11 @@
75
76 g_main_loop_run(handshake->mainloop);
77
78- if (handshake->timeout != 0)
79- g_source_remove(handshake->timeout);
80+ if (handshake->timeout != NULL) {
81+ g_source_destroy(handshake->timeout);
82+ g_source_unref(handshake->timeout);
83+ handshake->timeout = NULL;
84+ }
85 g_main_loop_unref(handshake->mainloop);
86 g_dbus_connection_signal_unsubscribe(handshake->con, handshake->signal_subscribe);
87 g_object_unref(handshake->con);
88
89=== modified file 'helpers.h'
90--- helpers.h 2015-07-15 02:32:54 +0000
91+++ helpers.h 2016-08-04 14:02:19 +0000
92@@ -19,6 +19,8 @@
93
94 #include <gio/gio.h>
95
96+G_BEGIN_DECLS
97+
98 typedef struct _EnvHandle EnvHandle;
99
100 gboolean app_id_to_triplet (const gchar * app_id,
101@@ -56,3 +58,6 @@
102
103 gboolean verify_keyfile (GKeyFile * inkeyfile,
104 const gchar * desktop);
105+
106+G_END_DECLS
107+
108
109=== modified file 'libubuntu-app-launch/CMakeLists.txt'
110--- libubuntu-app-launch/CMakeLists.txt 2016-08-04 14:02:18 +0000
111+++ libubuntu-app-launch/CMakeLists.txt 2016-08-04 14:02:19 +0000
112@@ -41,25 +41,26 @@
113 registry-impl.cpp
114 application-impl-base.h
115 application-impl-base.cpp
116+application-impl-click.h
117 application-impl-click.cpp
118 application-impl-legacy.h
119 application-impl-legacy.cpp
120 application-impl-libertine.h
121 application-impl-libertine.cpp
122+application-info-desktop.h
123 application-info-desktop.cpp
124+application-icon-finder.h
125 application-icon-finder.cpp
126 helper-impl-click.cpp
127+glib-thread.h
128 glib-thread.cpp
129 )
130
131 set(LAUNCHER_SOURCES
132 ubuntu-app-launch.cpp
133 second-exec-core.c
134-click-exec.c
135-desktop-exec.c
136 ubuntu-app-launch-trace.c
137 app-info.c
138-${LAUNCHER_CPP_SOURCES}
139 )
140
141 add_custom_target(format
142
143=== modified file 'libubuntu-app-launch/app-info.c'
144--- libubuntu-app-launch/app-info.c 2015-08-12 02:52:05 +0000
145+++ libubuntu-app-launch/app-info.c 2016-08-04 14:02:19 +0000
146@@ -21,10 +21,12 @@
147 #include <click.h>
148
149 #include "ubuntu-app-launch.h"
150-#include "app-info.h"
151+
152+/* Prototypes */
153+static gboolean app_info_libertine (const gchar * appid, gchar ** appdir, gchar ** appdesktop);
154
155 /* Try and get a manifest and do a couple sanity checks on it */
156-JsonObject *
157+static JsonObject *
158 get_manifest (const gchar * pkg, gchar ** pkgpath)
159 {
160 /* Get the directory from click */
161@@ -76,130 +78,6 @@
162 return manifest;
163 }
164
165-/* Types of search we can do for an app name */
166-typedef enum _app_name_t app_name_t;
167-enum _app_name_t {
168- APP_NAME_ONLY,
169- APP_NAME_FIRST,
170- APP_NAME_LAST
171-};
172-
173-/* Figure out the app name if it's one of the keywords */
174-static const gchar *
175-manifest_app_name (JsonObject ** manifest, const gchar * pkg, const gchar * original_app)
176-{
177- app_name_t app_type = APP_NAME_FIRST;
178-
179- if (original_app == NULL) {
180- /* first */
181- } else if (g_strcmp0(original_app, "first-listed-app") == 0) {
182- /* first */
183- } else if (g_strcmp0(original_app, "last-listed-app") == 0) {
184- app_type = APP_NAME_LAST;
185- } else if (g_strcmp0(original_app, "only-listed-app") == 0) {
186- app_type = APP_NAME_ONLY;
187- } else {
188- return original_app;
189- }
190-
191- if (*manifest == NULL) {
192- *manifest = get_manifest(pkg, NULL);
193- }
194-
195- JsonObject * hooks = json_object_get_object_member(*manifest, "hooks");
196-
197- if (hooks == NULL) {
198- return NULL;
199- }
200-
201- GList * apps = json_object_get_members(hooks);
202- if (apps == NULL) {
203- return NULL;
204- }
205-
206- const gchar * retapp = NULL;
207-
208- switch (app_type) {
209- case APP_NAME_ONLY:
210- if (g_list_length(apps) == 1) {
211- retapp = (const gchar *)apps->data;
212- }
213- break;
214- case APP_NAME_FIRST:
215- retapp = (const gchar *)apps->data;
216- break;
217- case APP_NAME_LAST:
218- retapp = (const gchar *)(g_list_last(apps)->data);
219- break;
220- default:
221- break;
222- }
223-
224- g_list_free(apps);
225-
226- return retapp;
227-}
228-
229-/* Figure out the app version using the manifest */
230-static const gchar *
231-manifest_version (JsonObject ** manifest, const gchar * pkg, const gchar * original_ver)
232-{
233- if (original_ver != NULL && g_strcmp0(original_ver, "current-user-version") != 0) {
234- return original_ver;
235- } else {
236- if (*manifest == NULL) {
237- *manifest = get_manifest(pkg, NULL);
238- }
239- g_return_val_if_fail(*manifest != NULL, NULL);
240-
241- return g_strdup(json_object_get_string_member(*manifest, "version"));
242- }
243-
244- return NULL;
245-}
246-
247-/* A click triplet can require using the Click DB and getting a
248- manifest. This code does that to look up the versions */
249-gchar *
250-click_triplet_to_app_id (const gchar * pkg, const gchar * app, const gchar * ver)
251-{
252- const gchar * version = NULL;
253- const gchar * application = NULL;
254- JsonObject * manifest = NULL;
255-
256- version = manifest_version(&manifest, pkg, ver);
257- g_return_val_if_fail(version != NULL, NULL);
258-
259- application = manifest_app_name(&manifest, pkg, app);
260- g_return_val_if_fail(application != NULL, NULL);
261-
262- gchar * retval = g_strdup_printf("%s_%s_%s", pkg, application, version);
263-
264- /* The object may hold allocation for some of our strings used above */
265- if (manifest)
266- json_object_unref(manifest);
267-
268- return retval;
269-}
270-
271-/* Build an appid how we think it should exist and then make sure
272- we can find it. Then pull it together. */
273-gchar *
274-libertine_triplet_to_app_id (const gchar * pkg, const gchar * app, const gchar * ver)
275-{
276- if (app == NULL) {
277- return NULL;
278- }
279-
280- gchar * synthappid = g_strdup_printf("%s_%s_0.0", pkg, app);
281- if (app_info_libertine(synthappid, NULL, NULL)) {
282- return synthappid;
283- } else {
284- g_free(synthappid);
285- return NULL;
286- }
287-}
288-
289 /* Look to see if the app id results in a desktop file, if so, fill in the params */
290 static gboolean
291 evaluate_dir (const gchar * dir, const gchar * desktop, gchar ** appdir, gchar ** appdesktop)
292@@ -224,7 +102,7 @@
293 }
294
295 /* Handle the legacy case where we look through the data directories */
296-gboolean
297+static gboolean
298 app_info_legacy (const gchar * appid, gchar ** appdir, gchar ** appdesktop)
299 {
300 gchar * desktop = g_strdup_printf("%s.desktop", appid);
301@@ -248,7 +126,7 @@
302 }
303
304 /* Handle the libertine case where we look in the container */
305-gboolean
306+static gboolean
307 app_info_libertine (const gchar * appid, gchar ** appdir, gchar ** appdesktop)
308 {
309 char * container = NULL;
310@@ -301,7 +179,7 @@
311 }
312
313 /* Get the information on where the desktop file is from libclick */
314-gboolean
315+static gboolean
316 app_info_click (const gchar * appid, gchar ** appdir, gchar ** appdesktop)
317 {
318 gchar * package = NULL;
319@@ -352,3 +230,48 @@
320 return TRUE;
321 }
322
323+/* Determine whether it's a click package by looking for the symlink
324+ that is created by the desktop hook */
325+static gboolean
326+is_click (const gchar * appid)
327+{
328+ gchar * appiddesktop = g_strdup_printf("%s.desktop", appid);
329+ gchar * click_link = NULL;
330+ const gchar * link_farm_dir = g_getenv("UBUNTU_APP_LAUNCH_LINK_FARM");
331+ if (G_LIKELY(link_farm_dir == NULL)) {
332+ click_link = g_build_filename(g_get_home_dir(), ".cache", "ubuntu-app-launch", "desktop", appiddesktop, NULL);
333+ } else {
334+ click_link = g_build_filename(link_farm_dir, appiddesktop, NULL);
335+ }
336+ g_free(appiddesktop);
337+ gboolean click = g_file_test(click_link, G_FILE_TEST_EXISTS);
338+ g_free(click_link);
339+
340+ return click;
341+}
342+
343+/* Determine whether an AppId is realated to a Libertine container by
344+ checking the container and program name. */
345+static gboolean
346+is_libertine (const gchar * appid)
347+{
348+ if (app_info_libertine(appid, NULL, NULL)) {
349+ g_debug("Libertine application detected: %s", appid);
350+ return TRUE;
351+ } else {
352+ return FALSE;
353+ }
354+}
355+
356+gboolean
357+ubuntu_app_launch_application_info (const gchar * appid, gchar ** appdir, gchar ** appdesktop)
358+{
359+ if (is_click(appid)) {
360+ return app_info_click(appid, appdir, appdesktop);
361+ } else if (is_libertine(appid)) {
362+ return app_info_libertine(appid, appdir, appdesktop);
363+ } else {
364+ return app_info_legacy(appid, appdir, appdesktop);
365+ }
366+}
367+
368
369=== removed file 'libubuntu-app-launch/app-info.h'
370--- libubuntu-app-launch/app-info.h 2016-08-04 14:02:18 +0000
371+++ libubuntu-app-launch/app-info.h 1970-01-01 00:00:00 +0000
372@@ -1,35 +0,0 @@
373-/*
374- * Copyright © 2015 Canonical Ltd.
375- *
376- * This program is free software: you can redistribute it and/or modify it
377- * under the terms of the GNU General Public License version 3, as published
378- * by the Free Software Foundation.
379- *
380- * This program is distributed in the hope that it will be useful, but
381- * WITHOUT ANY WARRANTY; without even the implied warranties of
382- * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
383- * PURPOSE. See the GNU General Public License for more details.
384- *
385- * You should have received a copy of the GNU General Public License along
386- * with this program. If not, see <http://www.gnu.org/licenses/>.
387- *
388- * Authors:
389- * Ted Gould <ted.gould@canonical.com>
390- */
391-
392-#pragma once
393-
394-#include <gio/gio.h>
395-
396-G_BEGIN_DECLS
397-
398-gboolean app_info_legacy (const gchar * appid, gchar ** appdir, gchar ** appdesktop);
399-gboolean app_info_libertine (const gchar * appid, gchar ** appdir, gchar ** appdesktop);
400-gboolean app_info_click (const gchar * appid, gchar ** appdir, gchar ** appdesktop);
401-
402-gchar * click_triplet_to_app_id (const gchar * pkg, const gchar * app, const gchar * ver);
403-gchar * libertine_triplet_to_app_id (const gchar * pkg, const gchar * app, const gchar * ver);
404-
405-gboolean start_application_core (GDBusConnection * con, GCancellable * cancel, const gchar * appid, const gchar * const * uris, gboolean test);
406-
407-G_END_DECLS
408
409=== modified file 'libubuntu-app-launch/appid.h'
410--- libubuntu-app-launch/appid.h 2016-04-18 18:29:32 +0000
411+++ libubuntu-app-launch/appid.h 2016-08-04 14:02:19 +0000
412@@ -29,6 +29,8 @@
413 namespace app_launch
414 {
415
416+class Registry;
417+
418 /** \brief The set of information that is used to uniquely identify an
419 application in Ubuntu.
420
421@@ -104,9 +106,21 @@
422 It can be used, but is slower than parse() if you've got well formed data
423 already.
424
425+ \note This will use the default registry instance, it is generally
426+ recommended to have your own instead of using the default.
427+
428 \param sappid String with the concatenated AppID
429 */
430 static AppID find(const std::string& sappid);
431+ /** Find is a more tollerant version of parse(), it handles legacy applications,
432+ short AppIDs ($package_$app) and other forms of that are in common usage.
433+ It can be used, but is slower than parse() if you've got well formed data
434+ already.
435+
436+ \param registry Registry instance to use for persistant connections
437+ \param sappid String with the concatenated AppID
438+ */
439+ static AppID find(const std::shared_ptr<Registry>& registry, const std::string& sappid);
440 /** Check to see whether a string is a valid AppID string
441
442 \param sappid String with the concatenated AppID
443@@ -130,6 +144,9 @@
444 /** Find the AppID for an application where you only know the package
445 name.
446
447+ \note This will use the default registry instance, it is generally
448+ recommended to have your own instead of using the default.
449+
450 \param package Name of the package
451 \param appwildcard Specification of how to search the manifest for apps
452 \param versionwildcard Specification of how to search for the version
453@@ -140,6 +157,9 @@
454 /** Find the AppID for an application where you know the package
455 name and application name.
456
457+ \note This will use the default registry instance, it is generally
458+ recommended to have your own instead of using the default.
459+
460 \param package Name of the package
461 \param appname Name of the application
462 \param versionwildcard Specification of how to search for the version
463@@ -149,15 +169,55 @@
464 VersionWildcard versionwildcard = VersionWildcard::CURRENT_USER_VERSION);
465 /** Create an AppID providing known strings of packages and names
466
467+ \note This will use the default registry instance, it is generally
468+ recommended to have your own instead of using the default.
469+
470 \param package Name of the package
471 \param appname Name of the application
472 \param version Version of the package
473 */
474 static AppID discover(const std::string& package, const std::string& appname, const std::string& version);
475+
476+ /** Find the AppID for an application where you only know the package
477+ name.
478+
479+ \param registry Registry instance to use for persistant connections
480+ \param package Name of the package
481+ \param appwildcard Specification of how to search the manifest for apps
482+ \param versionwildcard Specification of how to search for the version
483+ */
484+ static AppID discover(const std::shared_ptr<Registry>& registry,
485+ const std::string& package,
486+ ApplicationWildcard appwildcard = ApplicationWildcard::FIRST_LISTED,
487+ VersionWildcard versionwildcard = VersionWildcard::CURRENT_USER_VERSION);
488+ /** Find the AppID for an application where you know the package
489+ name and application name.
490+
491+ \param registry Registry instance to use for persistant connections
492+ \param package Name of the package
493+ \param appname Name of the application
494+ \param versionwildcard Specification of how to search for the version
495+ */
496+ static AppID discover(const std::shared_ptr<Registry>& registry,
497+ const std::string& package,
498+ const std::string& appname,
499+ VersionWildcard versionwildcard = VersionWildcard::CURRENT_USER_VERSION);
500+ /** Create an AppID providing known strings of packages and names
501+
502+ \param registry Registry instance to use for persistant connections
503+ \param package Name of the package
504+ \param appname Name of the application
505+ \param version Version of the package
506+ */
507+ static AppID discover(const std::shared_ptr<Registry>& registry,
508+ const std::string& package,
509+ const std::string& appname,
510+ const std::string& version);
511 };
512
513 bool operator==(const AppID& a, const AppID& b);
514 bool operator!=(const AppID& a, const AppID& b);
515+bool operator<(const AppID& a, const AppID& b);
516
517 }; // namespace app_launch
518 }; // namespace ubuntu
519
520=== modified file 'libubuntu-app-launch/application-impl-base.cpp'
521--- libubuntu-app-launch/application-impl-base.cpp 2016-08-04 14:02:18 +0000
522+++ libubuntu-app-launch/application-impl-base.cpp 2016-08-04 14:02:19 +0000
523@@ -25,9 +25,10 @@
524
525 #include <upstart.h>
526
527-#include "app-info.h"
528 #include "application-impl-base.h"
529+#include "helpers.h"
530 #include "registry-impl.h"
531+#include "second-exec-core.h"
532
533 namespace ubuntu
534 {
535@@ -46,6 +47,49 @@
536 return !instances().empty();
537 }
538
539+std::list<std::pair<std::string, std::string>> Base::confinedEnv(const std::string& package, const std::string& pkgdir)
540+{
541+ std::list<std::pair<std::string, std::string>> retval{{"UBUNTU_APPLICATION_ISOLATION", "1"}};
542+
543+ /* C Funcs can return null, which offends std::string */
544+ auto cset = [&retval](const gchar* key, const gchar* value) {
545+ if (value != nullptr)
546+ {
547+ g_debug("Setting '%s' to '%s'", key, value);
548+ retval.emplace_back(std::make_pair(key, value));
549+ }
550+ };
551+
552+ cset("XDG_CACHE_HOME", g_get_user_cache_dir());
553+ cset("XDG_CONFIG_HOME", g_get_user_config_dir());
554+ cset("XDG_DATA_HOME", g_get_user_data_dir());
555+ cset("XDG_RUNTIME_DIR", g_get_user_runtime_dir());
556+
557+ /* Add the application's dir to the list of sources for data */
558+ const gchar* basedatadirs = g_getenv("XDG_DATA_DIRS");
559+ if (basedatadirs == NULL || basedatadirs[0] == '\0')
560+ {
561+ basedatadirs = "/usr/local/share:/usr/share";
562+ }
563+ gchar* datadirs = g_strjoin(":", pkgdir.c_str(), basedatadirs, NULL);
564+ cset("XDG_DATA_DIRS", datadirs);
565+ g_free(datadirs);
566+
567+ /* Set TMPDIR to something sane and application-specific */
568+ gchar* tmpdir = g_strdup_printf("%s/confined/%s", g_get_user_runtime_dir(), package.c_str());
569+ cset("TMPDIR", tmpdir);
570+ g_debug("Creating '%s'", tmpdir);
571+ g_mkdir_with_parents(tmpdir, 0700);
572+ g_free(tmpdir);
573+
574+ /* Do the same for nvidia */
575+ gchar* nv_shader_cachedir = g_strdup_printf("%s/%s", g_get_user_cache_dir(), package.c_str());
576+ cset("__GL_SHADER_DISK_CACHE_PATH", nv_shader_cachedir);
577+ g_free(nv_shader_cachedir);
578+
579+ return retval;
580+}
581+
582 bool UpstartInstance::isRunning()
583 {
584 return primaryPid() != 0;
585@@ -157,17 +201,20 @@
586
587 std::string UpstartInstance::logPath()
588 {
589- auto cpath = ubuntu_app_launch_application_log_path(std::string(appId_).c_str());
590- if (cpath != nullptr)
591- {
592- std::string retval(cpath);
593- g_free(cpath);
594- return retval;
595- }
596- else
597- {
598- return {};
599- }
600+ std::string logfile = job_;
601+ if (!instance_.empty())
602+ {
603+ logfile += "-";
604+ logfile += instance_;
605+ }
606+
607+ logfile += ".log";
608+
609+ gchar* cpath = g_build_filename(g_get_user_cache_dir(), "upstart", logfile.c_str(), nullptr);
610+ std::string path(cpath);
611+ g_free(cpath);
612+
613+ return path;
614 }
615
616 std::vector<pid_t> UpstartInstance::pids()
617@@ -209,7 +256,65 @@
618
619 void UpstartInstance::stop()
620 {
621- ubuntu_app_launch_stop_application(std::string(appId_).c_str());
622+ if (!registry_->impl->thread.executeOnThread<bool>([this]() {
623+
624+ g_debug("Stopping job %s app_id %s instance_id %s", job_.c_str(), std::string(appId_).c_str(),
625+ instance_.c_str());
626+
627+ auto jobpath = registry_->impl->upstartJobPath(job_);
628+ if (jobpath.empty())
629+ {
630+ throw new std::runtime_error("Unable to get job path for Upstart job '" + job_ + "'");
631+ }
632+
633+ GVariantBuilder builder;
634+ g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
635+ g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY);
636+
637+ g_variant_builder_add_value(
638+ &builder, g_variant_new_take_string(g_strdup_printf("APP_ID=%s", std::string(appId_).c_str())));
639+
640+ if (!instance_.empty())
641+ {
642+ g_variant_builder_add_value(
643+ &builder, g_variant_new_take_string(g_strdup_printf("INSTANCE_ID=%s", instance_.c_str())));
644+ }
645+
646+ g_variant_builder_close(&builder);
647+ g_variant_builder_add_value(&builder, g_variant_new_boolean(FALSE)); /* wait */
648+
649+ GError* error = NULL;
650+ GVariant* stop_variant =
651+ g_dbus_connection_call_sync(registry_->impl->_dbus.get(), /* Dbus */
652+ DBUS_SERVICE_UPSTART, /* Upstart name */
653+ jobpath.c_str(), /* path */
654+ DBUS_INTERFACE_UPSTART_JOB, /* interface */
655+ "Stop", /* method */
656+ g_variant_builder_end(&builder), /* params */
657+ NULL, /* return */
658+ G_DBUS_CALL_FLAGS_NONE, /* flags */
659+ -1, /* timeout: default */
660+ registry_->impl->thread.getCancellable().get(), /* cancelable */
661+ &error); /* error (hopefully not) */
662+
663+ if (stop_variant != nullptr)
664+ {
665+ g_variant_unref(stop_variant);
666+ }
667+
668+ if (error != NULL)
669+ {
670+ g_warning("Unable to stop job %s app_id %s instance_id %s: %s", job_.c_str(),
671+ std::string(appId_).c_str(), instance_.c_str(), error->message);
672+ g_error_free(error);
673+ return false;
674+ }
675+
676+ return true;
677+ }))
678+ {
679+ g_warning("Unable to stop Upstart instance");
680+ }
681 }
682
683 /** Sets the OOM adjustment by getting the list of PIDs and writing
684@@ -461,15 +566,19 @@
685 UpstartInstance::UpstartInstance(const AppID& appId,
686 const std::string& job,
687 const std::string& instance,
688+ const std::vector<Application::URL>& urls,
689 const std::shared_ptr<Registry>& registry)
690 : appId_(appId)
691 , job_(job)
692 , instance_(instance)
693+ , urls_(urls)
694 , registry_(registry)
695 {
696+ g_debug("Creating a new UpstartInstance for '%s' instance '%s'", std::string(appId_).c_str(), instance.c_str());
697 }
698
699-std::shared_ptr<gchar*> urlsToStrv(const std::vector<Application::URL>& urls)
700+/** Reformat a C++ vector of URLs into a C GStrv of strings */
701+std::shared_ptr<gchar*> UpstartInstance::urlsToStrv(const std::vector<Application::URL>& urls)
702 {
703 if (urls.empty())
704 {
705@@ -481,32 +590,176 @@
706 for (auto url : urls)
707 {
708 auto str = g_strdup(url.value().c_str());
709+ g_debug("Converting URL: %s", str);
710 g_array_append_val(array, str);
711 }
712
713 return std::shared_ptr<gchar*>((gchar**)g_array_free(array, FALSE), g_strfreev);
714 }
715
716-std::shared_ptr<UpstartInstance> UpstartInstance::launch(const AppID& appId,
717- const std::string& job,
718- const std::string& instance,
719- const std::vector<Application::URL>& urls,
720- const std::shared_ptr<Registry>& registry,
721- launchMode mode)
722-{
723- auto urlstrv = urlsToStrv(urls);
724- auto start_result = registry->impl->thread.executeOnThread<gboolean>([registry, &appId, &urlstrv, &mode]() {
725- return start_application_core(registry->impl->_dbus.get(), registry->impl->thread.getCancellable().get(),
726- std::string(appId).c_str(), urlstrv.get(),
727- mode == launchMode::STANDARD ? FALSE : TRUE);
728- });
729-
730- if (start_result == FALSE)
731+/** Small helper that we can new/delete to work better with C stuff */
732+struct StartCHelper
733+{
734+ std::shared_ptr<UpstartInstance> ptr;
735+};
736+
737+/** Callback from starting an application. It checks to see whether the
738+ app is already running. If it is already running then we need to send
739+ the URLs to it via DBus. */
740+void UpstartInstance::application_start_cb(GObject* obj, GAsyncResult* res, gpointer user_data)
741+{
742+ StartCHelper* data = reinterpret_cast<StartCHelper*>(user_data);
743+ GError* error{nullptr};
744+ GVariant* result{nullptr};
745+
746+ // ual_tracepoint(libual_start_message_callback, std::string(data->appId_).c_str());
747+
748+ g_debug("Started Message Callback: %s", std::string(data->ptr->appId_).c_str());
749+
750+ result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(obj), res, &error);
751+
752+ if (result != nullptr)
753+ g_variant_unref(result);
754+
755+ if (error != nullptr)
756 {
757+ if (g_dbus_error_is_remote_error(error))
758+ {
759+ gchar* remote_error = g_dbus_error_get_remote_error(error);
760+ g_debug("Remote error: %s", remote_error);
761+ if (g_strcmp0(remote_error, "com.ubuntu.Upstart0_6.Error.AlreadyStarted") == 0)
762+ {
763+ auto urls = urlsToStrv(data->ptr->urls_);
764+ second_exec(data->ptr->registry_->impl->_dbus.get(), /* DBus */
765+ data->ptr->registry_->impl->thread.getCancellable().get(), /* cancellable */
766+ data->ptr->primaryPid(), /* primary pid */
767+ std::string(data->ptr->appId_).c_str(), /* appid */
768+ urls.get()); /* urls */
769+ }
770+
771+ g_free(remote_error);
772+ }
773+ else
774+ {
775+ g_warning("Unable to emit event to start application: %s", error->message);
776+ }
777+ g_error_free(error);
778+ }
779+
780+ delete data;
781+}
782+
783+std::shared_ptr<UpstartInstance> UpstartInstance::launch(
784+ const AppID& appId,
785+ const std::string& job,
786+ const std::string& instance,
787+ const std::vector<Application::URL>& urls,
788+ const std::shared_ptr<Registry>& registry,
789+ launchMode mode,
790+ std::function<std::list<std::pair<std::string, std::string>>(void)> getenv)
791+{
792+ if (appId.empty())
793 return {};
794- }
795-
796- return std::make_shared<UpstartInstance>(appId, job, instance, registry);
797+
798+ return registry->impl->thread.executeOnThread<std::shared_ptr<UpstartInstance>>(
799+ [&]() -> std::shared_ptr<UpstartInstance> {
800+ g_debug("Initializing params for an new UpstartInstance for: %s", std::string(appId).c_str());
801+
802+ // ual_tracepoint(libual_start, appid);
803+ handshake_t* handshake = starting_handshake_start(std::string(appId).c_str());
804+ if (handshake == NULL)
805+ {
806+ g_warning("Unable to setup starting handshake");
807+ }
808+
809+ /* Figure out the DBus path for the job */
810+ auto jobpath = registry->impl->upstartJobPath(job);
811+
812+ /* Build up our environment */
813+ std::list<std::pair<std::string, std::string>> env{
814+ {"APP_ID", std::string(appId)}, /* Application ID */
815+ {"APP_LAUNCHER_PID", std::to_string(getpid())}, /* Who we are, for bugs */
816+ };
817+
818+ if (!urls.empty())
819+ {
820+ env.emplace_back(std::make_pair(
821+ "APP_URIS", std::accumulate(urls.begin(), urls.end(), std::string{},
822+ [](const std::string& prev, Application::URL thisurl) {
823+ gchar* gescaped = g_shell_quote(thisurl.value().c_str());
824+ std::string escaped;
825+ if (gescaped != nullptr)
826+ {
827+ escaped = gescaped;
828+ g_free(gescaped);
829+ }
830+ else
831+ {
832+ g_warning("Unable to escape URL: %s", thisurl.value().c_str());
833+ return prev;
834+ }
835+
836+ if (prev.empty())
837+ {
838+ return escaped;
839+ }
840+ else
841+ {
842+ return prev + " " + escaped;
843+ }
844+ })));
845+ }
846+
847+ if (mode == launchMode::TEST)
848+ {
849+ env.emplace_back(std::make_pair("QT_LOAD_TESTABILITY", "1"));
850+ }
851+
852+ env.splice(env.end(), getenv());
853+
854+ /* Convert to GVariant */
855+ GVariantBuilder builder;
856+ g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
857+
858+ g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY);
859+
860+ for (auto envvar : env)
861+ {
862+ g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf(
863+ "%s=%s", envvar.first.c_str(), envvar.second.c_str())));
864+ }
865+
866+ g_variant_builder_close(&builder);
867+ g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE));
868+
869+ auto retval = std::make_shared<UpstartInstance>(appId, job, instance, urls, registry);
870+ auto chelper = new StartCHelper{};
871+ chelper->ptr = retval;
872+
873+ // ual_tracepoint(handshake_wait, app_id);
874+ starting_handshake_wait(handshake);
875+ // ual_tracepoint(handshake_complete, app_id);
876+
877+ /* Call the job start function */
878+ g_debug("Asking Upstart to start task for: %s", std::string(appId).c_str());
879+ g_dbus_connection_call(registry->impl->_dbus.get(), /* bus */
880+ DBUS_SERVICE_UPSTART, /* service name */
881+ jobpath.c_str(), /* Path */
882+ DBUS_INTERFACE_UPSTART_JOB, /* interface */
883+ "Start", /* method */
884+ g_variant_builder_end(&builder), /* params */
885+ NULL, /* return */
886+ G_DBUS_CALL_FLAGS_NONE, /* flags */
887+ -1, /* default timeout */
888+ registry->impl->thread.getCancellable().get(), /* cancelable */
889+ application_start_cb, /* callback */
890+ chelper /* object */
891+ );
892+
893+ // ual_tracepoint(libual_start_message_sent, appid);
894+
895+ return retval;
896+ });
897 }
898
899 }; // namespace app_impls
900
901=== modified file 'libubuntu-app-launch/application-impl-base.h'
902--- libubuntu-app-launch/application-impl-base.h 2016-08-04 14:02:18 +0000
903+++ libubuntu-app-launch/application-impl-base.h 2016-08-04 14:02:19 +0000
904@@ -21,6 +21,7 @@
905
906 extern "C" {
907 #include "ubuntu-app-launch.h"
908+#include <gio/gio.h>
909 }
910
911 #pragma once
912@@ -32,6 +33,9 @@
913 namespace app_impls
914 {
915
916+/** Provides some helper functions that can be used by all
917+ implementations of application. Stores the registry pointer
918+ which everyone wants anyway. */
919 class Base : public ubuntu::app_launch::Application
920 {
921 public:
922@@ -40,15 +44,24 @@
923 bool hasInstances() override;
924
925 protected:
926+ /** Pointer to the registry so we can ask it for things */
927 std::shared_ptr<Registry> _registry;
928+
929+ static std::list<std::pair<std::string, std::string>> confinedEnv(const std::string& package,
930+ const std::string& pkgdir);
931 };
932
933+/** An object that represents an instance of a job on Upstart. This
934+ then implements everything needed by the instance interface. Most
935+ applications tie into this today and use it as the backend for
936+ their instances. */
937 class UpstartInstance : public Application::Instance
938 {
939 public:
940 explicit UpstartInstance(const AppID& appId,
941 const std::string& job,
942 const std::string& instance,
943+ const std::vector<Application::URL>& urls,
944 const std::shared_ptr<Registry>& registry);
945
946 /* Query lifecycle */
947@@ -67,23 +80,32 @@
948 void setOomAdjustment(const oom::Score score) override;
949 const oom::Score getOomAdjustment() override;
950
951- /* Creating by launch */
952+ /** Flag for whether we should include the testing environment variables */
953 enum class launchMode
954 {
955- STANDARD,
956- TEST
957+ STANDARD, /**< Standard variable set */
958+ TEST /**< Include testing environment vars */
959 };
960- static std::shared_ptr<UpstartInstance> launch(const AppID& appId,
961- const std::string& job,
962- const std::string& instance,
963- const std::vector<Application::URL>& urls,
964- const std::shared_ptr<Registry>& registry,
965- launchMode mode);
966+ static std::shared_ptr<UpstartInstance> launch(
967+ const AppID& appId,
968+ const std::string& job,
969+ const std::string& instance,
970+ const std::vector<Application::URL>& urls,
971+ const std::shared_ptr<Registry>& registry,
972+ launchMode mode,
973+ std::function<std::list<std::pair<std::string, std::string>>(void)> getenv);
974
975 private:
976+ /** Application ID */
977 const AppID appId_;
978+ /** Upstart job name */
979 const std::string job_;
980+ /** Instance ID environment value, empty if none */
981 const std::string instance_;
982+ /** The URLs that this was launched for. Only valid on launched jobs, we
983+ should look at perhaps changing that. */
984+ std::vector<Application::URL> urls_;
985+ /** A link to the registry we're using for connections */
986 std::shared_ptr<Registry> registry_;
987
988 std::vector<pid_t> forAllPids(std::function<void(pid_t)> eachPid);
989@@ -92,6 +114,9 @@
990 void oomValueToPid(pid_t pid, const oom::Score oomvalue);
991 void oomValueToPidHelper(pid_t pid, const oom::Score oomvalue);
992 void pidListToDbus(const std::vector<pid_t>& pids, const std::string& signal);
993+
994+ static std::shared_ptr<gchar*> urlsToStrv(const std::vector<Application::URL>& urls);
995+ static void application_start_cb(GObject* obj, GAsyncResult* res, gpointer user_data);
996 };
997
998 }; // namespace app_impls
999
1000=== modified file 'libubuntu-app-launch/application-impl-click.cpp'
1001--- libubuntu-app-launch/application-impl-click.cpp 2016-08-04 14:02:18 +0000
1002+++ libubuntu-app-launch/application-impl-click.cpp 2016-08-04 14:02:19 +0000
1003@@ -47,7 +47,7 @@
1004 , _appid(appid)
1005 , _manifest(manifest)
1006 , _clickDir(registry->impl->getClickDir(appid.package))
1007- , _keyfile(manifestAppDesktop(manifest, appid.package, appid.appname, _clickDir))
1008+ , _keyfile(manifestAppDesktop(_manifest, appid.package, appid.appname, _clickDir))
1009 {
1010 if (!_keyfile)
1011 throw std::runtime_error{"No keyfile found for click application: " + (std::string)appid};
1012@@ -58,9 +58,90 @@
1013 return _appid;
1014 }
1015
1016+bool Click::hasAppId(const AppID& appid, const std::shared_ptr<Registry>& registry)
1017+{
1018+ std::string appiddesktop = std::string(appid) + ".desktop";
1019+ gchar* click_link = nullptr;
1020+ const gchar* link_farm_dir = g_getenv("UBUNTU_APP_LAUNCH_LINK_FARM");
1021+ if (G_LIKELY(link_farm_dir == nullptr))
1022+ {
1023+ click_link =
1024+ g_build_filename(g_get_user_cache_dir(), "ubuntu-app-launch", "desktop", appiddesktop.c_str(), NULL);
1025+ }
1026+ else
1027+ {
1028+ click_link = g_build_filename(link_farm_dir, appiddesktop.c_str(), NULL);
1029+ }
1030+
1031+ bool click = g_file_test(click_link, G_FILE_TEST_EXISTS);
1032+ g_free(click_link);
1033+
1034+ return click;
1035+}
1036+
1037+bool Click::verifyPackage(const AppID::Package& package, const std::shared_ptr<Registry>& registry)
1038+{
1039+ return registry->impl->getClickManifest(package) != nullptr;
1040+}
1041+
1042+bool Click::verifyAppname(const AppID::Package& package,
1043+ const AppID::AppName& appname,
1044+ const std::shared_ptr<Registry>& registry)
1045+{
1046+ auto manifest = registry->impl->getClickManifest(package);
1047+ auto apps = manifestApps(manifest);
1048+
1049+ return std::find_if(apps.begin(), apps.end(), [&appname](const AppID::AppName& listApp) -> bool {
1050+ return appname.value() == listApp.value();
1051+ }) != apps.end();
1052+}
1053+
1054+AppID::AppName Click::findAppname(const AppID::Package& package,
1055+ AppID::ApplicationWildcard card,
1056+ const std::shared_ptr<Registry>& registry)
1057+{
1058+ auto manifest = registry->impl->getClickManifest(package);
1059+ auto apps = manifestApps(manifest);
1060+
1061+ if (apps.size() == 0)
1062+ {
1063+ throw std::runtime_error("No apps in package '" + package.value() + "' to find");
1064+ }
1065+
1066+ switch (card)
1067+ {
1068+ case AppID::ApplicationWildcard::FIRST_LISTED:
1069+ return *apps.begin();
1070+ case AppID::ApplicationWildcard::LAST_LISTED:
1071+ return *apps.rbegin();
1072+ case AppID::ApplicationWildcard::ONLY_LISTED:
1073+ if (apps.size() != 1)
1074+ {
1075+ throw std::runtime_error("More than a single app in package '" + package.value() +
1076+ "' when requested to find only app");
1077+ }
1078+ return *apps.begin();
1079+ }
1080+
1081+ throw std::logic_error("Got a value of the app wildcard enum that can't exist");
1082+}
1083+
1084+AppID::Version Click::findVersion(const AppID::Package& package,
1085+ const AppID::AppName& appname,
1086+ const std::shared_ptr<Registry>& registry)
1087+{
1088+ auto manifest = registry->impl->getClickManifest(package);
1089+ return manifestVersion(manifest);
1090+}
1091+
1092 std::shared_ptr<Application::Info> Click::info()
1093 {
1094- return std::make_shared<app_info::Desktop>(_keyfile, _clickDir);
1095+ if (!_info)
1096+ {
1097+ _info = std::make_shared<app_info::Desktop>(_keyfile, _clickDir);
1098+ }
1099+
1100+ return _info;
1101 }
1102
1103 AppID::Version manifestVersion(const std::shared_ptr<JsonObject>& manifest)
1104@@ -198,23 +279,41 @@
1105 there or return an empty vector */
1106 if (sappid == instancename)
1107 {
1108- vect.emplace_back(std::make_shared<UpstartInstance>(appId(), "application-click", sappid, _registry));
1109+ vect.emplace_back(std::make_shared<UpstartInstance>(appId(), "application-click", sappid,
1110+ std::vector<Application::URL>{}, _registry));
1111 break;
1112 }
1113 }
1114 return vect;
1115 }
1116
1117+std::list<std::pair<std::string, std::string>> Click::launchEnv()
1118+{
1119+ auto retval = confinedEnv(_appid.package, _clickDir);
1120+
1121+ retval.emplace_back(std::make_pair("APP_DIR", _clickDir));
1122+
1123+ /* TODO: Not sure how we're gonna get this */
1124+ /* APP_DESKTOP_FILE_PATH */
1125+
1126+ info();
1127+
1128+ retval.emplace_back(std::make_pair("APP_XMIR_ENABLE", _info->xMirEnable().value() ? "1" : "0"));
1129+ retval.emplace_back(std::make_pair("APP_EXEC", _info->execLine().value()));
1130+
1131+ return retval;
1132+}
1133+
1134 std::shared_ptr<Application::Instance> Click::launch(const std::vector<Application::URL>& urls)
1135 {
1136 return UpstartInstance::launch(appId(), "application-click", std::string(appId()), urls, _registry,
1137- UpstartInstance::launchMode::STANDARD);
1138+ UpstartInstance::launchMode::STANDARD, [this]() { return launchEnv(); });
1139 }
1140
1141 std::shared_ptr<Application::Instance> Click::launchTest(const std::vector<Application::URL>& urls)
1142 {
1143 return UpstartInstance::launch(appId(), "application-click", std::string(appId()), urls, _registry,
1144- UpstartInstance::launchMode::TEST);
1145+ UpstartInstance::launchMode::TEST, [this]() { return launchEnv(); });
1146 }
1147
1148 }; // namespace app_impls
1149
1150=== modified file 'libubuntu-app-launch/application-impl-click.h'
1151--- libubuntu-app-launch/application-impl-click.h 2016-08-04 14:02:18 +0000
1152+++ libubuntu-app-launch/application-impl-click.h 2016-08-04 14:02:19 +0000
1153@@ -17,9 +17,11 @@
1154 * Ted Gould <ted.gould@canonical.com>
1155 */
1156
1157+#include "application-impl-base.h"
1158+#include "application-info-desktop.h"
1159+
1160 #include <gio/gdesktopappinfo.h>
1161 #include <json-glib/json-glib.h>
1162-#include "application-impl-base.h"
1163
1164 #pragma once
1165
1166@@ -44,8 +46,22 @@
1167
1168 std::vector<std::shared_ptr<Instance>> instances() override;
1169
1170- std::shared_ptr<Instance> launch(const std::vector<Application::URL> &urls = {}) override;
1171- std::shared_ptr<Instance> launchTest(const std::vector<Application::URL> &urls = {}) override;
1172+ std::shared_ptr<Instance> launch(const std::vector<Application::URL>& urls = {}) override;
1173+ std::shared_ptr<Instance> launchTest(const std::vector<Application::URL>& urls = {}) override;
1174+
1175+ static bool hasAppId(const AppID& appId, const std::shared_ptr<Registry>& registry);
1176+
1177+ static bool verifyPackage(const AppID::Package& package, const std::shared_ptr<Registry>& registry);
1178+ static bool verifyAppname(const AppID::Package& package,
1179+ const AppID::AppName& appname,
1180+ const std::shared_ptr<Registry>& registry);
1181+ static AppID::AppName findAppname(const AppID::Package& package,
1182+ AppID::ApplicationWildcard card,
1183+ const std::shared_ptr<Registry>& registry);
1184+ static AppID::Version findVersion(const AppID::Package& package,
1185+ const AppID::AppName& appname,
1186+ const std::shared_ptr<Registry>& registry);
1187+
1188 private:
1189 AppID _appid;
1190
1191@@ -53,6 +69,10 @@
1192
1193 std::string _clickDir;
1194 std::shared_ptr<GKeyFile> _keyfile;
1195+
1196+ std::shared_ptr<app_info::Desktop> _info;
1197+
1198+ std::list<std::pair<std::string, std::string>> launchEnv();
1199 };
1200
1201 }; // namespace app_impls
1202
1203=== modified file 'libubuntu-app-launch/application-impl-legacy.cpp'
1204--- libubuntu-app-launch/application-impl-legacy.cpp 2016-08-04 14:02:18 +0000
1205+++ libubuntu-app-launch/application-impl-legacy.cpp 2016-08-04 14:02:19 +0000
1206@@ -40,27 +40,18 @@
1207 }
1208 }
1209
1210-Legacy::Legacy(const AppID::AppName& appname,
1211- const std::string& basedir,
1212- const std::shared_ptr<GKeyFile>& keyfile,
1213- const std::shared_ptr<Registry>& registry)
1214- : Base(registry)
1215- , _appname(appname)
1216- , _basedir(basedir)
1217- , _keyfile(keyfile)
1218-{
1219- if (!_keyfile)
1220- throw std::runtime_error{"Unable to find keyfile for legacy application: " + appname.value()};
1221-}
1222-
1223 Legacy::Legacy(const AppID::AppName& appname, const std::shared_ptr<Registry>& registry)
1224 : Base(registry)
1225 , _appname(appname)
1226 {
1227 std::tie(_basedir, _keyfile) = keyfileForApp(appname);
1228
1229+ appinfo_ = std::make_shared<app_info::Desktop>(_keyfile, _basedir, _registry, true, false);
1230+
1231 if (!_keyfile)
1232+ {
1233 throw std::runtime_error{"Unable to find keyfile for legacy application: " + appname.value()};
1234+ }
1235 }
1236
1237 std::pair<std::string, std::shared_ptr<GKeyFile>> keyfileForApp(const AppID::AppName& name)
1238@@ -105,13 +96,79 @@
1239
1240 std::shared_ptr<Application::Info> Legacy::info()
1241 {
1242- if (!appinfo_)
1243- {
1244- appinfo_ = std::make_shared<app_info::Desktop>(_keyfile, _basedir, _registry, true);
1245- }
1246 return appinfo_;
1247 }
1248
1249+bool Legacy::hasAppId(const AppID& appid, const std::shared_ptr<Registry>& registry)
1250+{
1251+ try
1252+ {
1253+ if (!appid.version.value().empty())
1254+ {
1255+ return false;
1256+ }
1257+
1258+ return verifyAppname(appid.package, appid.appname, registry);
1259+ }
1260+ catch (std::runtime_error& e)
1261+ {
1262+ return false;
1263+ }
1264+}
1265+
1266+bool Legacy::verifyPackage(const AppID::Package& package, const std::shared_ptr<Registry>& registry)
1267+{
1268+ return package.value().empty();
1269+}
1270+
1271+bool Legacy::verifyAppname(const AppID::Package& package,
1272+ const AppID::AppName& appname,
1273+ const std::shared_ptr<Registry>& registry)
1274+{
1275+ if (!verifyPackage(package, registry))
1276+ {
1277+ throw std::runtime_error{"Invalid Legacy package: " + std::string(package)};
1278+ }
1279+
1280+ std::string desktop = std::string(appname) + ".desktop";
1281+ std::function<bool(const gchar* dir)> evaldir = [&desktop](const gchar* dir) {
1282+ char* fulldir = g_build_filename(dir, "applications", desktop.c_str(), nullptr);
1283+ gboolean found = g_file_test(fulldir, G_FILE_TEST_EXISTS);
1284+ g_free(fulldir);
1285+ return found == TRUE;
1286+ };
1287+
1288+ if (evaldir(g_get_user_data_dir()))
1289+ {
1290+ return true;
1291+ }
1292+
1293+ const char* const* data_dirs = g_get_system_data_dirs();
1294+ for (int i = 0; data_dirs[i] != nullptr; i++)
1295+ {
1296+ if (evaldir(data_dirs[i]))
1297+ {
1298+ return true;
1299+ }
1300+ }
1301+
1302+ return false;
1303+}
1304+
1305+AppID::AppName Legacy::findAppname(const AppID::Package& package,
1306+ AppID::ApplicationWildcard card,
1307+ const std::shared_ptr<Registry>& registry)
1308+{
1309+ throw std::runtime_error("Legacy apps can't be discovered by package");
1310+}
1311+
1312+AppID::Version Legacy::findVersion(const AppID::Package& package,
1313+ const AppID::AppName& appname,
1314+ const std::shared_ptr<Registry>& registry)
1315+{
1316+ return AppID::Version::from_raw({});
1317+}
1318+
1319 const std::regex desktop_remover("^(.*)\\.desktop$");
1320
1321 std::list<std::shared_ptr<Application>> Legacy::list(const std::shared_ptr<Registry>& registry)
1322@@ -177,7 +234,8 @@
1323 g_debug("Looking at legacy instance: %s", instance.c_str());
1324 if (std::equal(startsWith.begin(), startsWith.end(), instance.begin()))
1325 {
1326- vect.emplace_back(std::make_shared<UpstartInstance>(appId(), "application-legacy", instance, _registry));
1327+ vect.emplace_back(std::make_shared<UpstartInstance>(appId(), "application-legacy", instance,
1328+ std::vector<Application::URL>{}, _registry));
1329 }
1330 }
1331
1332@@ -186,16 +244,72 @@
1333 return vect;
1334 }
1335
1336+std::list<std::pair<std::string, std::string>> Legacy::launchEnv(const std::string& instance)
1337+{
1338+ std::list<std::pair<std::string, std::string>> retval;
1339+
1340+ /* TODO: Not sure how we're gonna get this */
1341+ /* APP_DESKTOP_FILE_PATH */
1342+
1343+ info();
1344+
1345+ retval.emplace_back(std::make_pair("APP_XMIR_ENABLE", appinfo_->xMirEnable().value() ? "1" : "0"));
1346+ retval.emplace_back(std::make_pair("APP_EXEC", appinfo_->execLine().value()));
1347+
1348+ /* Honor the 'Path' key if it is in the desktop file */
1349+ if (g_key_file_has_key(_keyfile.get(), "Desktop Entry", "Path", nullptr))
1350+ {
1351+ gchar* path = g_key_file_get_string(_keyfile.get(), "Desktop Entry", "Path", nullptr);
1352+ retval.emplace_back(std::make_pair("APP_DIR", path));
1353+ g_free(path);
1354+ }
1355+
1356+ /* If they've asked for an Apparmor profile, let's use it! */
1357+ gchar* apparmor = g_key_file_get_string(_keyfile.get(), "Desktop Entry", "X-Ubuntu-AppArmor-Profile", nullptr);
1358+ if (apparmor != nullptr)
1359+ {
1360+ retval.emplace_back(std::make_pair("APP_EXEC_POLICY", apparmor));
1361+ g_free(apparmor);
1362+
1363+ retval.splice(retval.end(), confinedEnv(_appname, "/usr/share"));
1364+ }
1365+ else
1366+ {
1367+ retval.emplace_back(std::make_pair("APP_EXEC_POLICY", "unconfined"));
1368+ }
1369+
1370+ retval.emplace_back(std::make_pair("INSTANCE_ID", instance));
1371+
1372+ return retval;
1373+}
1374+
1375+std::string Legacy::getInstance()
1376+{
1377+ auto single = g_key_file_get_boolean(_keyfile.get(), "Desktop Entry", "X-Ubuntu-Single-Instance", nullptr);
1378+ if (single)
1379+ {
1380+ return {};
1381+ }
1382+ else
1383+ {
1384+ return std::to_string(g_get_real_time());
1385+ }
1386+}
1387+
1388 std::shared_ptr<Application::Instance> Legacy::launch(const std::vector<Application::URL>& urls)
1389 {
1390- return UpstartInstance::launch(appId(), "application-legacy", std::string(appId()) + "-", urls, _registry,
1391- UpstartInstance::launchMode::STANDARD);
1392+ std::string instance = getInstance();
1393+ return UpstartInstance::launch(appId(), "application-legacy", "-" + instance, urls, _registry,
1394+ UpstartInstance::launchMode::STANDARD,
1395+ [this, instance]() { return launchEnv(instance); });
1396 }
1397
1398 std::shared_ptr<Application::Instance> Legacy::launchTest(const std::vector<Application::URL>& urls)
1399 {
1400- return UpstartInstance::launch(appId(), "application-legacy", std::string(appId()) + "-", urls, _registry,
1401- UpstartInstance::launchMode::TEST);
1402+ std::string instance = getInstance();
1403+ return UpstartInstance::launch(appId(), "application-legacy", "-" + instance, urls, _registry,
1404+ UpstartInstance::launchMode::TEST,
1405+ [this, instance]() { return launchEnv(instance); });
1406 }
1407
1408 }; // namespace app_impls
1409
1410=== modified file 'libubuntu-app-launch/application-impl-legacy.h'
1411--- libubuntu-app-launch/application-impl-legacy.h 2016-08-04 14:02:18 +0000
1412+++ libubuntu-app-launch/application-impl-legacy.h 2016-08-04 14:02:19 +0000
1413@@ -35,10 +35,6 @@
1414 {
1415 public:
1416 Legacy(const AppID::AppName& appname, const std::shared_ptr<Registry>& registry);
1417- Legacy(const AppID::AppName& appname,
1418- const std::string& basedir,
1419- const std::shared_ptr<GKeyFile>& keyfile,
1420- const std::shared_ptr<Registry>& registry);
1421
1422 AppID appId() override
1423 {
1424@@ -54,11 +50,27 @@
1425 std::shared_ptr<Instance> launch(const std::vector<Application::URL>& urls = {}) override;
1426 std::shared_ptr<Instance> launchTest(const std::vector<Application::URL>& urls = {}) override;
1427
1428+ static bool hasAppId(const AppID& appId, const std::shared_ptr<Registry>& registry);
1429+
1430+ static bool verifyPackage(const AppID::Package& package, const std::shared_ptr<Registry>& registry);
1431+ static bool verifyAppname(const AppID::Package& package,
1432+ const AppID::AppName& appname,
1433+ const std::shared_ptr<Registry>& registry);
1434+ static AppID::AppName findAppname(const AppID::Package& package,
1435+ AppID::ApplicationWildcard card,
1436+ const std::shared_ptr<Registry>& registry);
1437+ static AppID::Version findVersion(const AppID::Package& package,
1438+ const AppID::AppName& appname,
1439+ const std::shared_ptr<Registry>& registry);
1440+
1441 private:
1442 AppID::AppName _appname;
1443 std::string _basedir;
1444 std::shared_ptr<GKeyFile> _keyfile;
1445 std::shared_ptr<app_info::Desktop> appinfo_;
1446+
1447+ std::list<std::pair<std::string, std::string>> launchEnv(const std::string& instance);
1448+ std::string getInstance();
1449 };
1450
1451 }; // namespace app_impls
1452
1453=== modified file 'libubuntu-app-launch/application-impl-libertine.cpp'
1454--- libubuntu-app-launch/application-impl-libertine.cpp 2016-08-04 14:02:18 +0000
1455+++ libubuntu-app-launch/application-impl-libertine.cpp 2016-08-04 14:02:19 +0000
1456@@ -18,7 +18,6 @@
1457 */
1458
1459 #include "application-impl-libertine.h"
1460-#include "application-info-desktop.h"
1461 #include "libertine.h"
1462 #include "registry-impl.h"
1463
1464@@ -107,6 +106,71 @@
1465 return keyfile;
1466 }
1467
1468+bool Libertine::hasAppId(const AppID& appid, const std::shared_ptr<Registry>& registry)
1469+{
1470+ try
1471+ {
1472+ if (appid.version.value() != "0.0")
1473+ {
1474+ return false;
1475+ }
1476+
1477+ return verifyAppname(appid.package, appid.appname, registry);
1478+ }
1479+ catch (std::runtime_error& e)
1480+ {
1481+ return false;
1482+ }
1483+}
1484+
1485+bool Libertine::verifyPackage(const AppID::Package& package, const std::shared_ptr<Registry>& registry)
1486+{
1487+ auto containers = std::shared_ptr<gchar*>(libertine_list_containers(), g_strfreev);
1488+
1489+ for (int i = 0; containers.get()[i] != nullptr; i++)
1490+ {
1491+ auto container = containers.get()[i];
1492+ if (std::string(container) == package.value())
1493+ {
1494+ return true;
1495+ }
1496+ }
1497+
1498+ return false;
1499+}
1500+
1501+bool Libertine::verifyAppname(const AppID::Package& package,
1502+ const AppID::AppName& appname,
1503+ const std::shared_ptr<Registry>& registry)
1504+{
1505+ auto apps = std::shared_ptr<gchar*>(libertine_list_apps_for_container(package.value().c_str()), g_strfreev);
1506+
1507+ for (int i = 0; apps.get()[i] != nullptr; i++)
1508+ {
1509+ auto appid = AppID::parse(apps.get()[i]);
1510+ if (appid.appname.value() == appname.value())
1511+ {
1512+ return true;
1513+ }
1514+ }
1515+
1516+ return false;
1517+}
1518+
1519+AppID::AppName Libertine::findAppname(const AppID::Package& package,
1520+ AppID::ApplicationWildcard card,
1521+ const std::shared_ptr<Registry>& registry)
1522+{
1523+ throw std::runtime_error("Legacy apps can't be discovered by package");
1524+}
1525+
1526+AppID::Version Libertine::findVersion(const AppID::Package& package,
1527+ const AppID::AppName& appname,
1528+ const std::shared_ptr<Registry>& registry)
1529+{
1530+ return AppID::Version::from_raw("0.0");
1531+}
1532+
1533 std::list<std::shared_ptr<Application>> Libertine::list(const std::shared_ptr<Registry>& registry)
1534 {
1535 std::list<std::shared_ptr<Application>> applist;
1536@@ -131,7 +195,11 @@
1537
1538 std::shared_ptr<Application::Info> Libertine::info()
1539 {
1540- return std::make_shared<app_info::Desktop>(_keyfile, _basedir, _registry);
1541+ if (!appinfo_)
1542+ {
1543+ appinfo_ = std::make_shared<app_info::Desktop>(_keyfile, _basedir, _registry, false, true);
1544+ }
1545+ return appinfo_;
1546 }
1547
1548 std::vector<std::shared_ptr<Application::Instance>> Libertine::instances()
1549@@ -142,23 +210,53 @@
1550 for (auto instancename : _registry->impl->upstartInstancesForJob("application-legacy"))
1551 {
1552 if (std::equal(sappid.begin(), sappid.end(), instancename.begin()))
1553- vect.emplace_back(
1554- std::make_shared<UpstartInstance>(appId(), "application-legacy", sappid + "-", _registry));
1555+ vect.emplace_back(std::make_shared<UpstartInstance>(appId(), "application-legacy", sappid + "-",
1556+ std::vector<Application::URL>{}, _registry));
1557 }
1558
1559 return vect;
1560 }
1561
1562+std::list<std::pair<std::string, std::string>> Libertine::launchEnv()
1563+{
1564+ std::list<std::pair<std::string, std::string>> retval;
1565+
1566+ /* TODO: Not sure how we're gonna get this */
1567+ /* APP_DESKTOP_FILE_PATH */
1568+
1569+ info();
1570+
1571+ retval.emplace_back(std::make_pair("APP_XMIR_ENABLE", appinfo_->xMirEnable().value() ? "1" : "0"));
1572+
1573+ /* The container is our confinement */
1574+ retval.emplace_back(std::make_pair("APP_EXEC_POLICY", "unconfined"));
1575+
1576+ auto libertine_launch = g_getenv("UBUNTU_APP_LAUNCH_LIBERTINE_LAUNCH");
1577+ if (libertine_launch == nullptr)
1578+ {
1579+ libertine_launch = LIBERTINE_LAUNCH;
1580+ }
1581+
1582+ auto desktopexec = appinfo_->execLine().value();
1583+ auto execline = std::string(libertine_launch) + " \"" + _container.value() + "\" " + desktopexec;
1584+ retval.emplace_back(std::make_pair("APP_EXEC", execline));
1585+
1586+ /* TODO: Go multi instance */
1587+ retval.emplace_back(std::make_pair("INSTANCE_ID", ""));
1588+
1589+ return retval;
1590+}
1591+
1592 std::shared_ptr<Application::Instance> Libertine::launch(const std::vector<Application::URL>& urls)
1593 {
1594 return UpstartInstance::launch(appId(), "application-legacy", std::string(appId()) + "-", urls, _registry,
1595- UpstartInstance::launchMode::STANDARD);
1596+ UpstartInstance::launchMode::STANDARD, [this]() { return launchEnv(); });
1597 }
1598
1599 std::shared_ptr<Application::Instance> Libertine::launchTest(const std::vector<Application::URL>& urls)
1600 {
1601 return UpstartInstance::launch(appId(), "application-legacy", std::string(appId()) + "-", urls, _registry,
1602- UpstartInstance::launchMode::TEST);
1603+ UpstartInstance::launchMode::TEST, [this]() { return launchEnv(); });
1604 }
1605
1606 }; // namespace app_impls
1607
1608=== modified file 'libubuntu-app-launch/application-impl-libertine.h'
1609--- libubuntu-app-launch/application-impl-libertine.h 2016-08-04 14:02:18 +0000
1610+++ libubuntu-app-launch/application-impl-libertine.h 2016-08-04 14:02:19 +0000
1611@@ -18,6 +18,7 @@
1612 */
1613
1614 #include "application-impl-base.h"
1615+#include "application-info-desktop.h"
1616 #include <gio/gdesktopappinfo.h>
1617
1618 #pragma once
1619@@ -50,11 +51,27 @@
1620 std::shared_ptr<Instance> launch(const std::vector<Application::URL>& urls = {}) override;
1621 std::shared_ptr<Instance> launchTest(const std::vector<Application::URL>& urls = {}) override;
1622
1623+ static bool hasAppId(const AppID& appId, const std::shared_ptr<Registry>& registry);
1624+
1625+ static bool verifyPackage(const AppID::Package& package, const std::shared_ptr<Registry>& registry);
1626+ static bool verifyAppname(const AppID::Package& package,
1627+ const AppID::AppName& appname,
1628+ const std::shared_ptr<Registry>& registry);
1629+ static AppID::AppName findAppname(const AppID::Package& package,
1630+ AppID::ApplicationWildcard card,
1631+ const std::shared_ptr<Registry>& registry);
1632+ static AppID::Version findVersion(const AppID::Package& package,
1633+ const AppID::AppName& appname,
1634+ const std::shared_ptr<Registry>& registry);
1635+
1636 private:
1637 AppID::Package _container;
1638 AppID::AppName _appname;
1639 std::shared_ptr<GKeyFile> _keyfile;
1640 std::string _basedir;
1641+ std::shared_ptr<app_info::Desktop> appinfo_;
1642+
1643+ std::list<std::pair<std::string, std::string>> launchEnv();
1644 };
1645
1646 }; // namespace app_impls
1647
1648=== modified file 'libubuntu-app-launch/application-info-desktop.cpp'
1649--- libubuntu-app-launch/application-info-desktop.cpp 2016-05-10 19:09:34 +0000
1650+++ libubuntu-app-launch/application-info-desktop.cpp 2016-08-04 14:02:19 +0000
1651@@ -157,7 +157,8 @@
1652 Desktop::Desktop(std::shared_ptr<GKeyFile> keyfile,
1653 const std::string& basePath,
1654 std::shared_ptr<Registry> registry,
1655- bool allowNoDisplay)
1656+ bool allowNoDisplay,
1657+ bool xMirDefault)
1658 : _keyfile([keyfile, allowNoDisplay]() {
1659 if (!keyfile)
1660 {
1661@@ -269,6 +270,8 @@
1662 , _rotatesWindow(
1663 boolFromKeyfile<Application::Info::RotatesWindow>(keyfile, "X-Ubuntu-Rotates-Window-Contents", false))
1664 , _ubuntuLifecycle(boolFromKeyfile<Application::Info::UbuntuLifecycle>(keyfile, "X-Ubuntu-Touch", false))
1665+ , _xMirEnable(boolFromKeyfile<XMirEnable>(keyfile, "X-Ubuntu-XMir-Enable", xMirDefault))
1666+ , _exec(stringFromKeyfile<Exec>(keyfile, "Exec"))
1667 {
1668 }
1669
1670
1671=== modified file 'libubuntu-app-launch/application-info-desktop.h'
1672--- libubuntu-app-launch/application-info-desktop.h 2016-04-29 18:51:31 +0000
1673+++ libubuntu-app-launch/application-info-desktop.h 2016-08-04 14:02:19 +0000
1674@@ -36,7 +36,8 @@
1675 Desktop(std::shared_ptr<GKeyFile> keyfile,
1676 const std::string& basePath,
1677 std::shared_ptr<Registry> registry = nullptr,
1678- bool allowNoDisplay = false);
1679+ bool allowNoDisplay = false,
1680+ bool xMirDefault = false);
1681
1682 const Application::Info::Name& name() override
1683 {
1684@@ -71,7 +72,21 @@
1685 return _ubuntuLifecycle;
1686 }
1687
1688-private:
1689+ struct XMirEnableTag;
1690+ typedef TypeTagger<XMirEnableTag, bool> XMirEnable;
1691+ virtual XMirEnable xMirEnable()
1692+ {
1693+ return _xMirEnable;
1694+ }
1695+
1696+ struct ExecTag;
1697+ typedef TypeTagger<ExecTag, std::string> Exec;
1698+ virtual Exec execLine()
1699+ {
1700+ return _exec;
1701+ }
1702+
1703+protected:
1704 std::shared_ptr<GKeyFile> _keyfile;
1705 std::string _basePath;
1706
1707@@ -83,6 +98,9 @@
1708 Application::Info::Orientations _supportedOrientations;
1709 Application::Info::RotatesWindow _rotatesWindow;
1710 Application::Info::UbuntuLifecycle _ubuntuLifecycle;
1711+
1712+ XMirEnable _xMirEnable;
1713+ Exec _exec;
1714 };
1715
1716 }; // namespace AppInfo
1717
1718=== modified file 'libubuntu-app-launch/application.cpp'
1719--- libubuntu-app-launch/application.cpp 2016-08-04 14:02:18 +0000
1720+++ libubuntu-app-launch/application.cpp 2016-08-04 14:02:19 +0000
1721@@ -18,7 +18,6 @@
1722 */
1723
1724 extern "C" {
1725-#include "app-info.h"
1726 #include "ubuntu-app-launch.h"
1727 }
1728
1729@@ -26,7 +25,9 @@
1730 #include "application-impl-legacy.h"
1731 #include "application-impl-libertine.h"
1732 #include "application.h"
1733+#include "registry.h"
1734
1735+#include <functional>
1736 #include <iostream>
1737 #include <regex>
1738
1739@@ -42,22 +43,21 @@
1740 throw std::runtime_error("AppID is empty");
1741 }
1742
1743- std::string sappid = appid;
1744- if (app_info_click(sappid.c_str(), NULL, NULL))
1745+ if (app_impls::Click::hasAppId(appid, registry))
1746 {
1747 return std::make_shared<app_impls::Click>(appid, registry);
1748 }
1749- else if (app_info_libertine(sappid.c_str(), NULL, NULL))
1750+ else if (app_impls::Libertine::hasAppId(appid, registry))
1751 {
1752 return std::make_shared<app_impls::Libertine>(appid.package, appid.appname, registry);
1753 }
1754- else if (app_info_legacy(sappid.c_str(), NULL, NULL))
1755+ else if (app_impls::Legacy::hasAppId(appid, registry))
1756 {
1757 return std::make_shared<app_impls::Legacy>(appid.appname, registry);
1758 }
1759 else
1760 {
1761- throw std::runtime_error("Invalid app ID: " + sappid);
1762+ throw std::runtime_error("Invalid app ID: " + std::string(appid));
1763 }
1764 }
1765
1766@@ -106,6 +106,12 @@
1767
1768 AppID AppID::find(const std::string& sappid)
1769 {
1770+ auto registry = Registry::getDefault();
1771+ return find(registry, sappid);
1772+}
1773+
1774+AppID AppID::find(const std::shared_ptr<Registry>& registry, const std::string& sappid)
1775+{
1776 std::smatch match;
1777
1778 if (std::regex_match(sappid, match, full_appid_regex))
1779@@ -115,7 +121,7 @@
1780 }
1781 else if (std::regex_match(sappid, match, short_appid_regex))
1782 {
1783- return discover(match[1].str(), match[2].str());
1784+ return discover(registry, match[1].str(), match[2].str());
1785 }
1786 else if (std::regex_match(sappid, match, legacy_appid_regex))
1787 {
1788@@ -156,67 +162,181 @@
1789 a.version.value() != b.version.value();
1790 }
1791
1792+bool operator<(const AppID& a, const AppID& b)
1793+{
1794+ return std::string(a) < std::string(b);
1795+}
1796+
1797 bool AppID::empty() const
1798 {
1799 return package.value().empty() && appname.value().empty() && version.value().empty();
1800 }
1801
1802-std::string app_wildcard(AppID::ApplicationWildcard card)
1803-{
1804- switch (card)
1805- {
1806- case AppID::ApplicationWildcard::FIRST_LISTED:
1807- return "first-listed-app";
1808- case AppID::ApplicationWildcard::LAST_LISTED:
1809- return "last-listed-app";
1810- case AppID::ApplicationWildcard::ONLY_LISTED:
1811- return "only-listed-app";
1812- }
1813-
1814- return "";
1815-}
1816-
1817-std::string ver_wildcard(AppID::VersionWildcard card)
1818-{
1819- switch (card)
1820- {
1821- case AppID::VersionWildcard::CURRENT_USER_VERSION:
1822- return "current-user-version";
1823- }
1824-
1825- return "";
1826+/* Basically we're making our own VTable of static functions. Static
1827+ functions don't go in the normal VTables, so we can't use our class
1828+ inheritance here to help. So we're just packing these puppies into
1829+ a data structure and itterating over it. */
1830+struct DiscoverTools
1831+{
1832+ std::function<bool(const AppID::Package& package, const std::shared_ptr<Registry>& registry)> verifyPackage;
1833+ std::function<bool(
1834+ const AppID::Package& package, const AppID::AppName& appname, const std::shared_ptr<Registry>& registry)>
1835+ verifyAppname;
1836+ std::function<AppID::AppName(
1837+ const AppID::Package& package, AppID::ApplicationWildcard card, const std::shared_ptr<Registry>& registry)>
1838+ findAppname;
1839+ std::function<AppID::Version(
1840+ const AppID::Package& package, const AppID::AppName& appname, const std::shared_ptr<Registry>& registry)>
1841+ findVersion;
1842+ std::function<bool(const AppID& appid, const std::shared_ptr<Registry>& registry)> hasAppId;
1843+};
1844+
1845+static const std::vector<DiscoverTools> discoverTools{
1846+ /* Click */
1847+ {app_impls::Click::verifyPackage, app_impls::Click::verifyAppname, app_impls::Click::findAppname,
1848+ app_impls::Click::findVersion, app_impls::Click::hasAppId},
1849+ /* Libertine */
1850+ {app_impls::Libertine::verifyPackage, app_impls::Libertine::verifyAppname, app_impls::Libertine::findAppname,
1851+ app_impls::Libertine::findVersion, app_impls::Libertine::hasAppId},
1852+ /* Legacy */
1853+ {app_impls::Legacy::verifyPackage, app_impls::Legacy::verifyAppname, app_impls::Legacy::findAppname,
1854+ app_impls::Legacy::findVersion, app_impls::Legacy::hasAppId}};
1855+
1856+AppID AppID::discover(const std::shared_ptr<Registry>& registry,
1857+ const std::string& package,
1858+ const std::string& appname,
1859+ const std::string& version)
1860+{
1861+ auto pkg = AppID::Package::from_raw(package);
1862+
1863+ for (auto tools : discoverTools)
1864+ {
1865+ /* Figure out which type we have */
1866+ try
1867+ {
1868+ if (tools.verifyPackage(pkg, registry))
1869+ {
1870+ auto app = AppID::AppName::from_raw({});
1871+
1872+ if (appname.empty() || appname == "first-listed-app")
1873+ {
1874+ app = tools.findAppname(pkg, ApplicationWildcard::FIRST_LISTED, registry);
1875+ }
1876+ else if (appname == "last-listed-app")
1877+ {
1878+ app = tools.findAppname(pkg, ApplicationWildcard::LAST_LISTED, registry);
1879+ }
1880+ else if (appname == "only-listed-app")
1881+ {
1882+ app = tools.findAppname(pkg, ApplicationWildcard::ONLY_LISTED, registry);
1883+ }
1884+ else
1885+ {
1886+ app = AppID::AppName::from_raw(appname);
1887+ if (!tools.verifyAppname(pkg, app, registry))
1888+ {
1889+ throw std::runtime_error("App name passed in is not valid for this package type");
1890+ }
1891+ }
1892+
1893+ auto ver = AppID::Version::from_raw({});
1894+ if (version.empty() || version == "current-user-version")
1895+ {
1896+ ver = tools.findVersion(pkg, app, registry);
1897+ }
1898+ else
1899+ {
1900+ ver = AppID::Version::from_raw(version);
1901+ if (!tools.hasAppId({pkg, app, ver}, registry))
1902+ {
1903+ throw std::runtime_error("Invalid version passed for this package type");
1904+ }
1905+ }
1906+
1907+ return AppID{pkg, app, ver};
1908+ }
1909+ }
1910+ catch (std::runtime_error& e)
1911+ {
1912+ continue;
1913+ }
1914+ }
1915+
1916+ return {};
1917+}
1918+
1919+AppID AppID::discover(const std::shared_ptr<Registry>& registry,
1920+ const std::string& package,
1921+ ApplicationWildcard appwildcard,
1922+ VersionWildcard versionwildcard)
1923+{
1924+ auto pkg = AppID::Package::from_raw(package);
1925+
1926+ for (auto tools : discoverTools)
1927+ {
1928+ try
1929+ {
1930+ if (tools.verifyPackage(pkg, registry))
1931+ {
1932+ auto app = tools.findAppname(pkg, appwildcard, registry);
1933+ auto ver = tools.findVersion(pkg, app, registry);
1934+ return AppID{pkg, app, ver};
1935+ }
1936+ }
1937+ catch (std::runtime_error& e)
1938+ {
1939+ /* Normal, try another */
1940+ continue;
1941+ }
1942+ }
1943+
1944+ return {};
1945+}
1946+
1947+AppID AppID::discover(const std::shared_ptr<Registry>& registry,
1948+ const std::string& package,
1949+ const std::string& appname,
1950+ VersionWildcard versionwildcard)
1951+{
1952+ auto pkg = AppID::Package::from_raw(package);
1953+ auto app = AppID::AppName::from_raw(appname);
1954+
1955+ for (auto tools : discoverTools)
1956+ {
1957+ try
1958+ {
1959+ if (tools.verifyPackage(pkg, registry) && tools.verifyAppname(pkg, app, registry))
1960+ {
1961+ auto ver = tools.findVersion(pkg, app, registry);
1962+ return AppID{pkg, app, ver};
1963+ }
1964+ }
1965+ catch (std::runtime_error& e)
1966+ {
1967+ /* Normal, try another */
1968+ continue;
1969+ }
1970+ }
1971+
1972+ return {};
1973 }
1974
1975 AppID AppID::discover(const std::string& package, const std::string& appname, const std::string& version)
1976 {
1977- auto cappid = ubuntu_app_launch_triplet_to_app_id(package.c_str(), appname.c_str(), version.c_str());
1978-
1979- auto appid = cappid != nullptr ? AppID::parse(cappid) : AppID::parse("");
1980-
1981- g_free(cappid);
1982-
1983- return appid;
1984+ auto registry = Registry::getDefault();
1985+ return discover(registry, package, appname, version);
1986 }
1987
1988 AppID AppID::discover(const std::string& package, ApplicationWildcard appwildcard, VersionWildcard versionwildcard)
1989 {
1990- return discover(package, app_wildcard(appwildcard), ver_wildcard(versionwildcard));
1991+ auto registry = Registry::getDefault();
1992+ return discover(registry, package, appwildcard, versionwildcard);
1993 }
1994
1995 AppID AppID::discover(const std::string& package, const std::string& appname, VersionWildcard versionwildcard)
1996 {
1997- auto appid = discover(package, appname, ver_wildcard(versionwildcard));
1998-
1999- if (appid.empty())
2000- {
2001- /* If we weren't able to go that route, we can see if it's libertine */
2002- if (app_info_libertine((package + "_" + appname + "_0.0").c_str(), nullptr, nullptr))
2003- {
2004- appid = AppID(Package::from_raw(package), AppName::from_raw(appname), Version::from_raw("0.0"));
2005- }
2006- }
2007-
2008- return appid;
2009+ auto registry = Registry::getDefault();
2010+ return discover(registry, package, appname, versionwildcard);
2011 }
2012
2013 enum class oom::Score : std::int32_t
2014
2015=== removed file 'libubuntu-app-launch/click-exec.c'
2016--- libubuntu-app-launch/click-exec.c 2014-09-17 14:11:59 +0000
2017+++ libubuntu-app-launch/click-exec.c 1970-01-01 00:00:00 +0000
2018@@ -1,170 +0,0 @@
2019-/*
2020- * Copyright 2013 Canonical Ltd.
2021- *
2022- * This program is free software: you can redistribute it and/or modify it
2023- * under the terms of the GNU General Public License version 3, as published
2024- * by the Free Software Foundation.
2025- *
2026- * This program is distributed in the hope that it will be useful, but
2027- * WITHOUT ANY WARRANTY; without even the implied warranties of
2028- * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2029- * PURPOSE. See the GNU General Public License for more details.
2030- *
2031- * You should have received a copy of the GNU General Public License along
2032- * with this program. If not, see <http://www.gnu.org/licenses/>.
2033- *
2034- * Authors:
2035- * Ted Gould <ted.gould@canonical.com>
2036- */
2037-
2038-#include <gio/gio.h>
2039-#include <click.h>
2040-#include "helpers.h"
2041-#include "ubuntu-app-launch-trace.h"
2042-#include "ual-tracepoint.h"
2043-
2044-/*
2045-
2046-INTRODUCTION:
2047-
2048-This is the utility that executes a click package based on the Application ID.
2049-Actually it just determines what needs to be executed, and asks Upstart to execute
2050-it so that it can be tracked better. This process runs OUTSIDE of the app armor
2051-confinement for the application. It also DOES NOT use any files that can be modified
2052-by the user. So things like the desktop file in ~/.local/share/applications are
2053-all off limits.
2054-
2055-For information on Click packages and the manifest look at the Click package documentation:
2056-
2057-https://click.readthedocs.org/en/latest/
2058-
2059-*/
2060-
2061-gboolean
2062-click_task_setup (GDBusConnection * bus, const gchar * app_id, EnvHandle * handle)
2063-{
2064- g_return_val_if_fail(bus != NULL, FALSE);
2065- g_return_val_if_fail(app_id != NULL, FALSE);
2066- g_return_val_if_fail(handle != NULL, FALSE);
2067-
2068- ual_tracepoint(click_start, app_id);
2069-
2070- GError * error = NULL;
2071-
2072- handshake_t * handshake = starting_handshake_start(app_id);
2073- if (handshake == NULL) {
2074- g_warning("Unable to setup starting handshake");
2075- }
2076-
2077- ual_tracepoint(click_starting_sent, app_id);
2078-
2079- gchar * package = NULL;
2080- /* 'Parse' the App ID */
2081- if (!app_id_to_triplet(app_id, &package, NULL, NULL)) {
2082- g_warning("Unable to parse App ID: '%s'", app_id);
2083- return FALSE;
2084- }
2085-
2086- /* Check click to find out where the files are */
2087- ClickDB * db = click_db_new();
2088- /* If TEST_CLICK_DB is unset, this reads the system database. */
2089- click_db_read(db, g_getenv("TEST_CLICK_DB"), &error);
2090- if (error != NULL) {
2091- g_warning("Unable to read Click database: %s", error->message);
2092- g_error_free(error);
2093- g_free(package);
2094- return FALSE;
2095- }
2096- /* If TEST_CLICK_USER is unset, this uses the current user name. */
2097- ClickUser * user = click_user_new_for_user(db, g_getenv("TEST_CLICK_USER"), &error);
2098- if (error != NULL) {
2099- g_warning("Unable to read Click database: %s", error->message);
2100- g_error_free(error);
2101- g_free(package);
2102- g_object_unref(db);
2103- return FALSE;
2104- }
2105- gchar * pkgdir = click_user_get_path(user, package, &error);
2106- if (error != NULL) {
2107- g_warning("Unable to get the Click package directory for %s: %s", package, error->message);
2108- g_error_free(error);
2109- g_free(package);
2110- g_object_unref(user);
2111- g_object_unref(db);
2112- return FALSE;
2113- }
2114- g_object_unref(user);
2115- g_object_unref(db);
2116-
2117- ual_tracepoint(click_found_pkgdir, app_id);
2118-
2119- if (!g_file_test(pkgdir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
2120- g_warning("Application directory '%s' doesn't exist", pkgdir);
2121- g_free(pkgdir);
2122- g_free(package);
2123- return FALSE;
2124- }
2125-
2126- g_debug("Setting 'APP_DIR' to '%s'", pkgdir);
2127- env_handle_add(handle, "APP_DIR", pkgdir);
2128-
2129- set_confined_envvars(handle, package, pkgdir);
2130-
2131- ual_tracepoint(click_configured_env, app_id);
2132-
2133- gchar * desktopfile = manifest_to_desktop(pkgdir, app_id);
2134-
2135- g_free(pkgdir);
2136- g_free(package);
2137-
2138- if (desktopfile == NULL) {
2139- g_warning("Desktop file unable to be found");
2140- return FALSE;
2141- }
2142-
2143- ual_tracepoint(click_read_manifest, app_id);
2144-
2145- GKeyFile * keyfile = g_key_file_new();
2146-
2147- env_handle_add(handle, "APP_DESKTOP_FILE_PATH", desktopfile);
2148- g_key_file_load_from_file(keyfile, desktopfile, 0, &error);
2149- if (error != NULL) {
2150- g_warning("Unable to load desktop file '%s': %s", desktopfile, error->message);
2151- g_error_free(error);
2152- g_key_file_free(keyfile);
2153- g_free(desktopfile);
2154- return FALSE;
2155- }
2156-
2157- if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) {
2158- if (g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) {
2159- env_handle_add(handle, "APP_XMIR_ENABLE", "1");
2160- } else {
2161- env_handle_add(handle, "APP_XMIR_ENABLE", "0");
2162- }
2163- }
2164-
2165- /* This string is quoted using desktop file quoting:
2166- http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables */
2167- gchar * exec = desktop_to_exec(keyfile, desktopfile);
2168- if (exec == NULL) {
2169- return FALSE;
2170- }
2171-
2172- ual_tracepoint(click_read_desktop, app_id);
2173-
2174- g_debug("Setting 'APP_EXEC' to '%s'", exec);
2175- env_handle_add(handle, "APP_EXEC", exec);
2176-
2177- g_free(exec);
2178- g_key_file_unref(keyfile);
2179- g_free(desktopfile);
2180-
2181- ual_tracepoint(handshake_wait, app_id);
2182-
2183- starting_handshake_wait(handshake);
2184-
2185- ual_tracepoint(handshake_complete, app_id);
2186-
2187- return TRUE;
2188-}
2189
2190=== removed file 'libubuntu-app-launch/click-exec.h'
2191--- libubuntu-app-launch/click-exec.h 2014-08-22 20:59:55 +0000
2192+++ libubuntu-app-launch/click-exec.h 1970-01-01 00:00:00 +0000
2193@@ -1,25 +0,0 @@
2194-/*
2195- * Copyright © 2014 Canonical Ltd.
2196- *
2197- * This program is free software: you can redistribute it and/or modify it
2198- * under the terms of the GNU General Public License version 3, as published
2199- * by the Free Software Foundation.
2200- *
2201- * This program is distributed in the hope that it will be useful, but
2202- * WITHOUT ANY WARRANTY; without even the implied warranties of
2203- * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2204- * PURPOSE. See the GNU General Public License for more details.
2205- *
2206- * You should have received a copy of the GNU General Public License along
2207- * with this program. If not, see <http://www.gnu.org/licenses/>.
2208- *
2209- * Authors:
2210- * Ted Gould <ted.gould@canonical.com>
2211- */
2212-
2213-#include <glib.h>
2214-#include "helpers.h"
2215-
2216-gboolean click_task_setup (GDBusConnection * bus, const gchar * app_id, EnvHandle * envhandle);
2217-
2218-
2219
2220=== removed file 'libubuntu-app-launch/desktop-exec.c'
2221--- libubuntu-app-launch/desktop-exec.c 2016-01-26 21:17:25 +0000
2222+++ libubuntu-app-launch/desktop-exec.c 1970-01-01 00:00:00 +0000
2223@@ -1,218 +0,0 @@
2224-/*
2225- * Copyright 2013 Canonical Ltd.
2226- *
2227- * This program is free software: you can redistribute it and/or modify it
2228- * under the terms of the GNU General Public License version 3, as published
2229- * by the Free Software Foundation.
2230- *
2231- * This program is distributed in the hope that it will be useful, but
2232- * WITHOUT ANY WARRANTY; without even the implied warranties of
2233- * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2234- * PURPOSE. See the GNU General Public License for more details.
2235- *
2236- * You should have received a copy of the GNU General Public License along
2237- * with this program. If not, see <http://www.gnu.org/licenses/>.
2238- *
2239- * Authors:
2240- * Ted Gould <ted.gould@canonical.com>
2241- */
2242-
2243-#include <unistd.h>
2244-#include <errno.h>
2245-#include <string.h>
2246-#include <glib.h>
2247-#include <gio/gio.h>
2248-
2249-#include "helpers.h"
2250-#include "ubuntu-app-launch-trace.h"
2251-#include "recoverable-problem.h"
2252-#include "ual-tracepoint.h"
2253-#include "ubuntu-app-launch.h"
2254-#include "app-info.h"
2255-
2256-/* Reports an error on the caller of UAL so that we can track
2257- who is trying to launch bad AppIDs, and then fix their bug
2258- so that we get better reporting upstream. */
2259-void
2260-report_error_on_caller (const gchar * app_id) {
2261- g_warning("Unable to find keyfile for application '%s'", app_id);
2262-
2263- const gchar * props[3] = {
2264- "AppId", NULL,
2265- NULL
2266- };
2267- props[1] = app_id;
2268-
2269- GPid pid = getpid();
2270-
2271- /* Checking to see if we're using the command line tool to create
2272- the appid. Chances are in that case it's a user error, and we
2273- don't need to automatically record it, the user mistyped. */
2274- gboolean debugtool = FALSE;
2275- if (pid != 0) {
2276- const gchar * cmdpath = "/proc/self/cmdline";
2277- gchar * cmdline = NULL;
2278-
2279- if (g_file_get_contents(cmdpath, &cmdline, NULL, NULL)) {
2280- if (g_strstr_len(cmdline, -1, "ubuntu-app-launch") != NULL) {
2281- debugtool = TRUE;
2282- }
2283-
2284- g_free(cmdline);
2285- } else {
2286- /* The caller has already exited, probably a debug tool */
2287- debugtool = TRUE;
2288- }
2289- }
2290-
2291- if (!debugtool) {
2292- report_recoverable_problem("ubuntu-app-launch-invalid-appid", pid, TRUE, props);
2293- } else {
2294- g_debug("Suppressing appid recoverable error for debug tool");
2295- }
2296-}
2297-
2298-/* Get the keyfile object for a libertine container based application. Look into
2299- the container's filesystem on disk and find it in /usr/share/applications in there.
2300- Those are currently the only apps that we look at today. We're not ensuring anything
2301- about the file other than it has basic sanity. */
2302-GKeyFile *
2303-keyfile_for_libertine (const gchar * appid, gchar ** outcontainer)
2304-{
2305- gchar * desktopfile = NULL;
2306- gchar * desktopdir = NULL;
2307-
2308- if (!app_info_libertine(appid, &desktopdir, &desktopfile)) {
2309- return NULL;
2310- }
2311-
2312- gchar * desktopfull = g_build_filename(desktopdir, desktopfile, NULL);
2313- g_debug("Desktop full: %s", desktopfull);
2314- g_free(desktopdir);
2315- g_free(desktopfile);
2316-
2317- /* We now think we have a valid 'desktopfile' path */
2318- GKeyFile * keyfile = g_key_file_new();
2319- gboolean loaded = g_key_file_load_from_file(keyfile, desktopfull, G_KEY_FILE_NONE, NULL);
2320-
2321- if (!loaded) {
2322- g_free(desktopfull);
2323- g_key_file_free(keyfile);
2324- return NULL;
2325- }
2326-
2327- if (!verify_keyfile(keyfile, desktopfull)) {
2328- g_free(desktopfull);
2329- g_key_file_free(keyfile);
2330- return NULL;
2331- }
2332-
2333- g_free(desktopfull);
2334-
2335- if (outcontainer != NULL) {
2336- ubuntu_app_launch_app_id_parse(appid, outcontainer, NULL, NULL);
2337- }
2338-
2339- return keyfile;
2340-}
2341-
2342-gboolean
2343-desktop_task_setup (GDBusConnection * bus, const gchar * app_id, EnvHandle * handle, gboolean is_libertine)
2344-{
2345- if (app_id == NULL) {
2346- g_error("No APP_ID environment variable defined");
2347- return FALSE;
2348- }
2349-
2350- ual_tracepoint(desktop_start, app_id);
2351-
2352- handshake_t * handshake = starting_handshake_start(app_id);
2353- if (handshake == NULL) {
2354- g_warning("Unable to setup starting handshake");
2355- }
2356-
2357- ual_tracepoint(desktop_starting_sent, app_id);
2358-
2359- gchar * desktopfilename = NULL;
2360- GKeyFile * keyfile = NULL;
2361- gchar * libertinecontainer = NULL;
2362- if (is_libertine) {
2363- /* desktopfilename not set, not useful in this context */
2364- keyfile = keyfile_for_libertine(app_id, &libertinecontainer);
2365- } else {
2366- keyfile = keyfile_for_appid(app_id, &desktopfilename);
2367- }
2368-
2369- if (keyfile == NULL) {
2370- report_error_on_caller(app_id);
2371- g_free(libertinecontainer);
2372- return FALSE;
2373- }
2374-
2375- ual_tracepoint(desktop_found, app_id);
2376-
2377- /* Desktop file name so that libs can get other info from it */
2378- if (desktopfilename != NULL) {
2379- env_handle_add(handle, "APP_DESKTOP_FILE_PATH", desktopfilename);
2380- g_free(desktopfilename);
2381- }
2382-
2383- if (g_key_file_has_key(keyfile, "Desktop Entry", "Path", NULL)) {
2384- gchar * path = g_key_file_get_string(keyfile, "Desktop Entry", "Path", NULL);
2385- env_handle_add(handle, "APP_DIR", path);
2386- g_free(path);
2387- }
2388-
2389- gchar * apparmor = g_key_file_get_string(keyfile, "Desktop Entry", "X-Ubuntu-AppArmor-Profile", NULL);
2390- if (apparmor != NULL) {
2391- env_handle_add(handle, "APP_EXEC_POLICY", apparmor);
2392- set_confined_envvars(handle, app_id, "/usr/share");
2393- g_free(apparmor);
2394- } else {
2395- env_handle_add(handle, "APP_EXEC_POLICY", "unconfined");
2396- }
2397-
2398- if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) {
2399- if (g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) {
2400- env_handle_add(handle, "APP_XMIR_ENABLE", "1");
2401- } else {
2402- env_handle_add(handle, "APP_XMIR_ENABLE", "0");
2403- }
2404- } else if (is_libertine) {
2405- /* Default to X for libertine stuff */
2406- env_handle_add(handle, "APP_XMIR_ENABLE", "1");
2407- }
2408-
2409- /* This string is quoted using desktop file quoting:
2410- http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables */
2411- gchar * execline = desktop_to_exec(keyfile, app_id);
2412- g_return_val_if_fail(execline != NULL, FALSE);
2413-
2414- if (is_libertine) {
2415- static const gchar * libertine_launch = NULL;
2416- if (G_UNLIKELY(libertine_launch == NULL)) {
2417- libertine_launch = g_getenv("UBUNTU_APP_LAUNCH_LIBERTINE_LAUNCH");
2418- if (libertine_launch == NULL) {
2419- libertine_launch = LIBERTINE_LAUNCH;
2420- }
2421- }
2422-
2423- gchar * libexec = g_strdup_printf("%s \"%s\" %s", libertine_launch, libertinecontainer, execline);
2424- g_free(execline);
2425- execline = libexec;
2426- }
2427- g_free(libertinecontainer); /* Handles NULL, let's be sure it goes away */
2428-
2429- env_handle_add(handle, "APP_EXEC", execline);
2430- g_free(execline);
2431-
2432- g_key_file_free(keyfile);
2433-
2434- ual_tracepoint(handshake_wait, app_id);
2435-
2436- starting_handshake_wait(handshake);
2437-
2438- ual_tracepoint(handshake_complete, app_id);
2439-
2440- return TRUE;
2441-}
2442
2443=== removed file 'libubuntu-app-launch/desktop-exec.h'
2444--- libubuntu-app-launch/desktop-exec.h 2015-07-15 02:12:04 +0000
2445+++ libubuntu-app-launch/desktop-exec.h 1970-01-01 00:00:00 +0000
2446@@ -1,26 +0,0 @@
2447-/*
2448- * Copyright © 2014 Canonical Ltd.
2449- *
2450- * This program is free software: you can redistribute it and/or modify it
2451- * under the terms of the GNU General Public License version 3, as published
2452- * by the Free Software Foundation.
2453- *
2454- * This program is distributed in the hope that it will be useful, but
2455- * WITHOUT ANY WARRANTY; without even the implied warranties of
2456- * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
2457- * PURPOSE. See the GNU General Public License for more details.
2458- *
2459- * You should have received a copy of the GNU General Public License along
2460- * with this program. If not, see <http://www.gnu.org/licenses/>.
2461- *
2462- * Authors:
2463- * Ted Gould <ted.gould@canonical.com>
2464- */
2465-
2466-#pragma once
2467-
2468-#include <glib.h>
2469-#include "helpers.h"
2470-
2471-gboolean desktop_task_setup (GDBusConnection * bus, const gchar * appid, EnvHandle * envhandle, gboolean is_libertine);
2472-
2473
2474=== modified file 'libubuntu-app-launch/registry.cpp'
2475--- libubuntu-app-launch/registry.cpp 2016-08-04 14:02:18 +0000
2476+++ libubuntu-app-launch/registry.cpp 2016-08-04 14:02:19 +0000
2477@@ -91,7 +91,7 @@
2478 std::list<std::shared_ptr<Application>> apps;
2479 for (auto instance : instanceset)
2480 {
2481- auto appid = AppID::find(instance);
2482+ auto appid = AppID::find(connection, instance);
2483 auto app = Application::create(appid, connection);
2484 apps.push_back(app);
2485 }
2486
2487=== modified file 'libubuntu-app-launch/second-exec-core.c'
2488--- libubuntu-app-launch/second-exec-core.c 2016-08-04 14:02:18 +0000
2489+++ libubuntu-app-launch/second-exec-core.c 2016-08-04 14:02:19 +0000
2490@@ -29,24 +29,38 @@
2491 typedef struct {
2492 GDBusConnection * bus;
2493 gchar * appid;
2494- gchar * input_uris;
2495+ gchar ** input_uris;
2496 GPid app_pid;
2497 guint connections_open;
2498 GVariant * app_data;
2499 gchar * dbus_path;
2500 guint64 unity_starttime;
2501- guint timer;
2502+ GSource * timer;
2503 guint signal;
2504 } second_exec_t;
2505
2506 static void second_exec_complete (second_exec_t * data);
2507
2508+static GSource *
2509+thread_default_timeout (guint interval, GSourceFunc func, gpointer data)
2510+{
2511+ GSource * src = g_timeout_source_new(interval);
2512+ GMainContext * context = g_main_context_get_thread_default();
2513+
2514+ g_source_set_callback(src, func, data, NULL);
2515+
2516+ g_source_attach(src, context);
2517+
2518+ return src;
2519+}
2520+
2521 /* Unity didn't respond in time, continue on */
2522 static gboolean
2523 timer_cb (gpointer user_data)
2524 {
2525 ual_tracepoint(second_exec_resume_timeout, ((second_exec_t *)user_data)->appid);
2526 g_warning("Unity didn't respond in 500ms to resume the app");
2527+
2528 second_exec_complete(user_data);
2529 return G_SOURCE_REMOVE;
2530 }
2531@@ -67,7 +81,7 @@
2532 second_exec_complete(data);
2533 } else {
2534 g_debug("Timer Set");
2535- data->timer = g_timeout_add(500 - (timespent / 1000), timer_cb, data);
2536+ data->timer = thread_default_timeout(500 - (timespent / 1000), timer_cb, data);
2537 }
2538 }
2539 return;
2540@@ -82,9 +96,10 @@
2541 g_debug("Unity Completed Resume");
2542 ual_tracepoint(second_exec_resume_complete, data->appid);
2543
2544- if (data->timer != 0) {
2545- g_source_remove(data->timer);
2546- data->timer = 0;
2547+ if (data->timer != NULL) {
2548+ g_source_destroy(data->timer);
2549+ g_source_unref(data->timer);
2550+ data->timer = NULL;
2551 }
2552
2553 if (data->connections_open == 0) {
2554@@ -107,31 +122,17 @@
2555 }
2556
2557 GVariant * uris = NULL;
2558- gchar ** uri_split = NULL;
2559- GError * error = NULL;
2560-
2561- g_shell_parse_argv(data->input_uris, NULL, &uri_split, &error);
2562-
2563- if (uri_split == NULL || uri_split[0] == NULL || error != NULL) {
2564- if (error != NULL) {
2565- g_warning("Unable to parse URLs '%s': %s", data->input_uris, error->message);
2566- g_error_free(error);
2567- }
2568-
2569+
2570+ if (data->input_uris == NULL) {
2571 uris = g_variant_new_array(G_VARIANT_TYPE_STRING, NULL, 0);
2572-
2573- if (uri_split != NULL) {
2574- g_strfreev(uri_split);
2575- }
2576 } else {
2577 GVariantBuilder builder;
2578 g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
2579
2580 int i;
2581- for (i = 0; uri_split[i] != NULL; i++) {
2582- g_variant_builder_add_value(&builder, g_variant_new_take_string(uri_split[i]));
2583+ for (i = 0; data->input_uris[i] != NULL; i++) {
2584+ g_variant_builder_add_value(&builder, g_variant_new_string(data->input_uris[i]));
2585 }
2586- g_free(uri_split);
2587
2588 uris = g_variant_builder_end(&builder);
2589 }
2590@@ -281,7 +282,7 @@
2591 }
2592
2593 /* Starts to look for the PID and the connections for that PID */
2594-void
2595+static void
2596 find_appid_pid (GDBusConnection * session, second_exec_t * data)
2597 {
2598 GError * error = NULL;
2599@@ -310,16 +311,6 @@
2600 g_debug("Got bus names");
2601 ual_tracepoint(second_exec_got_dbus_names, data->appid);
2602
2603- /* Next figure out what we're looking for (and if there is something to look for) */
2604- /* NOTE: We're getting the PID *after* the list of connections so
2605- that some new process can't come in, be the same PID as it's
2606- connection will not be in teh list we just got. */
2607- data->app_pid = ubuntu_app_launch_get_primary_pid(data->appid);
2608- if (data->app_pid == 0) {
2609- g_warning("Unable to find pid for app id '%s'", data->appid);
2610- return;
2611- }
2612-
2613 g_debug("Primary PID: %d", data->app_pid);
2614 ual_tracepoint(second_exec_got_primary_pid, data->appid);
2615
2616@@ -364,16 +355,17 @@
2617 }
2618
2619 gboolean
2620-second_exec (GDBusConnection * session, GCancellable * cancel, const gchar * app_id, const gchar * appuris)
2621+second_exec (GDBusConnection * session, GCancellable * cancel, GPid pid, const gchar * app_id, gchar ** appuris)
2622 {
2623- ual_tracepoint(second_exec_start, app_id, appuris);
2624+ ual_tracepoint(second_exec_start, app_id);
2625 GError * error = NULL;
2626
2627 /* Setup our continuation data */
2628 second_exec_t * data = g_new0(second_exec_t, 1);
2629 data->appid = g_strdup(app_id);
2630- data->input_uris = g_strdup(appuris);
2631+ data->input_uris = g_strdupv(appuris);
2632 data->bus = g_object_ref(session);
2633+ data->app_pid = pid;
2634
2635 /* Set up listening for the unfrozen signal from Unity */
2636 data->signal = g_dbus_connection_signal_subscribe(session,
2637@@ -414,11 +406,17 @@
2638 /* If we've got something to give out, start looking for how */
2639 if (data->input_uris != NULL) {
2640 find_appid_pid(session, data);
2641+ } else {
2642+ g_debug("No URIs to send");
2643 }
2644
2645 /* Loop and wait for everything to align */
2646- if (data->connections_open == 0 && data->unity_starttime == 0) {
2647- second_exec_complete(data);
2648+ if (data->connections_open == 0) {
2649+ if (data->unity_starttime == 0) {
2650+ second_exec_complete(data);
2651+ } else {
2652+ data->timer = thread_default_timeout(500, timer_cb, data);
2653+ }
2654 }
2655
2656 return TRUE;
2657@@ -461,11 +459,15 @@
2658 if (data->signal != 0)
2659 g_dbus_connection_signal_unsubscribe(data->bus, data->signal);
2660
2661+ if (data->timer != NULL) {
2662+ g_source_destroy(data->timer);
2663+ g_source_unref(data->timer);
2664+ }
2665 g_object_unref(data->bus);
2666 if (data->app_data != NULL)
2667 g_variant_unref(data->app_data);
2668 g_free(data->appid);
2669- g_free(data->input_uris);
2670+ g_strfreev(data->input_uris);
2671 g_free(data->dbus_path);
2672 g_free(data);
2673
2674
2675=== modified file 'libubuntu-app-launch/second-exec-core.h'
2676--- libubuntu-app-launch/second-exec-core.h 2016-08-04 14:02:18 +0000
2677+++ libubuntu-app-launch/second-exec-core.h 2016-08-04 14:02:19 +0000
2678@@ -20,5 +20,9 @@
2679
2680 #include <gio/gio.h>
2681
2682-gboolean second_exec (GDBusConnection * con, GCancellable * cancel, const gchar * app_id, const gchar * appuris);
2683+G_BEGIN_DECLS
2684+
2685+gboolean second_exec (GDBusConnection * con, GCancellable * cancel, GPid pid, const gchar * app_id, gchar ** appuris);
2686+
2687+G_END_DECLS
2688
2689
2690=== modified file 'libubuntu-app-launch/ubuntu-app-launch-trace.tp'
2691--- libubuntu-app-launch/ubuntu-app-launch-trace.tp 2015-07-15 01:42:22 +0000
2692+++ libubuntu-app-launch/ubuntu-app-launch-trace.tp 2016-08-04 14:02:19 +0000
2693@@ -67,10 +67,9 @@
2694 Second Exec tracking
2695 *******************************/
2696 TRACEPOINT_EVENT(ubuntu_app_launch, second_exec_start,
2697- TP_ARGS(const char *, appid, const char *, appuris),
2698+ TP_ARGS(const char *, appid),
2699 TP_FIELDS(
2700 ctf_string(appid, appid)
2701- ctf_string(appuris, appuris)
2702 )
2703 )
2704 TRACEPOINT_EVENT(ubuntu_app_launch, second_exec_emit_resume,
2705
2706=== modified file 'libubuntu-app-launch/ubuntu-app-launch.cpp'
2707--- libubuntu-app-launch/ubuntu-app-launch.cpp 2016-08-04 14:02:18 +0000
2708+++ libubuntu-app-launch/ubuntu-app-launch.cpp 2016-08-04 14:02:19 +0000
2709@@ -28,14 +28,10 @@
2710 #include <zeitgeist.h>
2711
2712 #include "ubuntu-app-launch-trace.h"
2713-#include "second-exec-core.h"
2714 #include "helpers.h"
2715 #include "ual-tracepoint.h"
2716-#include "click-exec.h"
2717-#include "desktop-exec.h"
2718 #include "recoverable-problem.h"
2719 #include "proxy-socket-demangler.h"
2720-#include "app-info.h"
2721 }
2722
2723 /* C++ Interface */
2724@@ -43,7 +39,6 @@
2725 #include "appid.h"
2726 #include "registry.h"
2727
2728-static void apps_for_job (GDBusConnection * con, const gchar * name, GArray * apps, gboolean truncate_legacy);
2729 static void free_helper (gpointer value);
2730 int kill (pid_t pid, int signal);
2731 static gchar * escape_dbus_string (const gchar * input);
2732@@ -71,51 +66,6 @@
2733 return urisjoin;
2734 }
2735
2736-typedef struct {
2737- gchar * appid;
2738- gchar * uris;
2739- GDBusConnection * con;
2740- GCancellable * cancel;
2741-} app_start_t;
2742-
2743-static void
2744-application_start_cb (GObject * obj, GAsyncResult * res, gpointer user_data)
2745-{
2746- app_start_t * data = (app_start_t *)user_data;
2747- GError * error = NULL;
2748- GVariant * result = NULL;
2749-
2750- ual_tracepoint(libual_start_message_callback, data->appid);
2751-
2752- g_debug("Started Message Callback: %s", data->appid);
2753-
2754- result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(obj), res, &error);
2755-
2756- if (result != NULL)
2757- g_variant_unref(result);
2758-
2759- if (error != NULL) {
2760- if (g_dbus_error_is_remote_error(error)) {
2761- gchar * remote_error = g_dbus_error_get_remote_error(error);
2762- g_debug("Remote error: %s", remote_error);
2763- if (g_strcmp0(remote_error, "com.ubuntu.Upstart0_6.Error.AlreadyStarted") == 0) {
2764- second_exec(data->con, data->cancel, data->appid, data->uris);
2765- }
2766-
2767- g_free(remote_error);
2768- } else {
2769- g_warning("Unable to emit event to start application: %s", error->message);
2770- }
2771- g_error_free(error);
2772- }
2773-
2774- g_clear_object(&data->con);
2775- g_clear_object(&data->cancel);
2776- g_free(data->appid);
2777- g_free(data->uris);
2778- g_free(data);
2779-}
2780-
2781 /* Get the path of the job from Upstart, if we've got it already, we'll just
2782 use the cache of the value */
2783 static const gchar *
2784@@ -159,246 +109,54 @@
2785 return job_path;
2786 }
2787
2788-/* Check to see if a legacy app wants us to manage whether they're
2789- single instance or not */
2790-static gboolean
2791-legacy_single_instance (const gchar * appid)
2792-{
2793- ual_tracepoint(desktop_single_start, appid);
2794-
2795- GKeyFile * keyfile = keyfile_for_appid(appid, NULL);
2796-
2797- if (keyfile == NULL) {
2798- g_warning("Unable to find keyfile for application '%s'", appid);
2799- return FALSE;
2800- }
2801-
2802- ual_tracepoint(desktop_single_found, appid);
2803-
2804- gboolean singleinstance = FALSE;
2805-
2806- if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", NULL)) {
2807- GError * error = NULL;
2808-
2809- singleinstance = g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", &error);
2810-
2811- if (error != NULL) {
2812- g_warning("Unable to get single instance key for app '%s': %s", appid, error->message);
2813- g_error_free(error);
2814- /* Ensure that if we got an error, we assume standard case */
2815- singleinstance = FALSE;
2816- }
2817- }
2818-
2819- g_key_file_free(keyfile);
2820-
2821- ual_tracepoint(desktop_single_finished, appid, singleinstance ? "single" : "unmanaged");
2822-
2823- return singleinstance;
2824-}
2825-
2826-/* Determine whether it's a click package by looking for the symlink
2827- that is created by the desktop hook */
2828-static gboolean
2829-is_click (const gchar * appid)
2830-{
2831- gchar * appiddesktop = g_strdup_printf("%s.desktop", appid);
2832- gchar * click_link = NULL;
2833- const gchar * link_farm_dir = g_getenv("UBUNTU_APP_LAUNCH_LINK_FARM");
2834- if (G_LIKELY(link_farm_dir == NULL)) {
2835- click_link = g_build_filename(g_get_home_dir(), ".cache", "ubuntu-app-launch", "desktop", appiddesktop, NULL);
2836- } else {
2837- click_link = g_build_filename(link_farm_dir, appiddesktop, NULL);
2838- }
2839- g_free(appiddesktop);
2840- gboolean click = g_file_test(click_link, G_FILE_TEST_EXISTS);
2841- g_free(click_link);
2842-
2843- return click;
2844-}
2845-
2846-/* Determine whether an AppId is realated to a Libertine container by
2847- checking the container and program name. */
2848-static gboolean
2849-is_libertine (const gchar * appid)
2850-{
2851- if (app_info_libertine(appid, NULL, NULL)) {
2852- g_debug("Libertine application detected: %s", appid);
2853- return TRUE;
2854- } else {
2855- return FALSE;
2856- }
2857-}
2858-
2859-gboolean
2860-start_application_core (GDBusConnection * con, GCancellable * cancel, const gchar * appid, const gchar * const * uris, gboolean test)
2861-{
2862- ual_tracepoint(libual_start, appid);
2863-
2864- g_return_val_if_fail(appid != NULL, FALSE);
2865-
2866- gboolean click = is_click(appid);
2867- ual_tracepoint(libual_determine_type, appid, click ? "click" : "legacy");
2868-
2869- /* Figure out if it is libertine */
2870- gboolean libertine = FALSE;
2871- if (!click) {
2872- libertine = is_libertine(appid);
2873- }
2874-
2875- ual_tracepoint(libual_determine_libertine, appid, libertine ? "container" : "host");
2876-
2877- /* Figure out the DBus path for the job */
2878- const gchar * jobpath = NULL;
2879- if (click) {
2880- jobpath = get_jobpath(con, "application-click");
2881- } else {
2882- jobpath = get_jobpath(con, "application-legacy");
2883- }
2884-
2885- if (jobpath == NULL) {
2886- g_object_unref(con);
2887- g_warning("Unable to get job path");
2888- return FALSE;
2889- }
2890-
2891- ual_tracepoint(libual_job_path_determined, appid, jobpath);
2892-
2893- /* Callback data */
2894- app_start_t * app_start_data = g_new0(app_start_t, 1);
2895- app_start_data->appid = g_strdup(appid);
2896- app_start_data->con = G_DBUS_CONNECTION(g_object_ref(con));
2897- app_start_data->cancel = cancel ? G_CANCELLABLE(g_object_ref(cancel)) : nullptr;
2898-
2899- /* Build up our environment */
2900- GVariantBuilder builder;
2901- g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
2902-
2903- g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY);
2904-
2905- g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("APP_ID=%s", appid)));
2906- g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("APP_LAUNCHER_PID=%d", getpid())));
2907-
2908- if (uris != NULL) {
2909- gchar * urisjoin = app_uris_string(uris);
2910- gchar * urienv = g_strdup_printf("APP_URIS=%s", urisjoin);
2911- app_start_data->uris = urisjoin;
2912- g_variant_builder_add_value(&builder, g_variant_new_take_string(urienv));
2913- }
2914-
2915- if (!click) {
2916- if (libertine || legacy_single_instance(appid)) {
2917- g_variant_builder_add_value(&builder, g_variant_new_string("INSTANCE_ID="));
2918- } else {
2919- gchar * instanceid = g_strdup_printf("INSTANCE_ID=%" G_GUINT64_FORMAT, g_get_real_time());
2920- g_variant_builder_add_value(&builder, g_variant_new_take_string(instanceid));
2921- }
2922- }
2923-
2924- if (test) {
2925- g_variant_builder_add_value(&builder, g_variant_new_string("QT_LOAD_TESTABILITY=1"));
2926- }
2927-
2928- gboolean setup_complete = FALSE;
2929- if (click) {
2930- setup_complete = click_task_setup(con, appid, (EnvHandle*)&builder);
2931- } else {
2932- setup_complete = desktop_task_setup(con, appid, (EnvHandle*)&builder, libertine);
2933- }
2934-
2935- if (setup_complete) {
2936- g_variant_builder_close(&builder);
2937- g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE));
2938-
2939- /* Call the job start function */
2940- g_dbus_connection_call(con,
2941- DBUS_SERVICE_UPSTART,
2942- jobpath,
2943- DBUS_INTERFACE_UPSTART_JOB,
2944- "Start",
2945- g_variant_builder_end(&builder),
2946- NULL,
2947- G_DBUS_CALL_FLAGS_NONE,
2948- -1,
2949- cancel, /* cancelable */
2950- application_start_cb,
2951- app_start_data);
2952-
2953- ual_tracepoint(libual_start_message_sent, appid);
2954- } else {
2955- g_variant_builder_clear(&builder);
2956- }
2957-
2958- return setup_complete;
2959-}
2960-
2961 gboolean
2962 ubuntu_app_launch_start_application (const gchar * appid, const gchar * const * uris)
2963 {
2964- GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
2965- g_return_val_if_fail(con != NULL, FALSE);
2966-
2967- auto coreret = start_application_core(con, nullptr, appid, uris, FALSE);
2968-
2969- g_object_unref(con);
2970- return coreret;
2971+ try {
2972+ auto registry = ubuntu::app_launch::Registry::getDefault();
2973+ auto appId = ubuntu::app_launch::AppID::find(appid);
2974+ auto app = ubuntu::app_launch::Application::create(appId, registry);
2975+
2976+ std::vector<ubuntu::app_launch::Application::URL> urivect;
2977+ for (auto i = 0; uris != nullptr && uris[i] != nullptr; i++)
2978+ urivect.emplace_back(ubuntu::app_launch::Application::URL::from_raw(uris[i]));
2979+
2980+ auto instance = app->launch(urivect);
2981+
2982+ if (instance) {
2983+ return TRUE;
2984+ } else {
2985+ return FALSE;
2986+ }
2987+ } catch (std::runtime_error &e) {
2988+ g_warning("Unable to start app '%s': %s", appid, e.what());
2989+ return FALSE;
2990+ }
2991 }
2992
2993 gboolean
2994 ubuntu_app_launch_start_application_test (const gchar * appid, const gchar * const * uris)
2995 {
2996- GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
2997- g_return_val_if_fail(con != NULL, FALSE);
2998-
2999- auto coreret = start_application_core(con, nullptr, appid, uris, TRUE);
3000-
3001- g_object_unref(con);
3002- return coreret;
3003-}
3004-
3005-static void
3006-stop_job (GDBusConnection * con, const gchar * jobname, const gchar * appname, const gchar * instanceid)
3007-{
3008- g_debug("Stopping job %s app_id %s instance_id %s", jobname, appname, instanceid);
3009-
3010- const gchar * job_path = get_jobpath(con, jobname);
3011- if (job_path == NULL)
3012- return;
3013-
3014- GVariantBuilder builder;
3015- g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
3016- g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY);
3017-
3018- g_variant_builder_add_value(&builder,
3019- g_variant_new_take_string(g_strdup_printf("APP_ID=%s", appname)));
3020-
3021- if (instanceid != NULL) {
3022- g_variant_builder_add_value(&builder,
3023- g_variant_new_take_string(g_strdup_printf("INSTANCE_ID=%s", instanceid)));
3024- }
3025-
3026- g_variant_builder_close(&builder);
3027- g_variant_builder_add_value(&builder, g_variant_new_boolean(FALSE)); /* wait */
3028-
3029- GError * error = NULL;
3030- GVariant * stop_variant = g_dbus_connection_call_sync(con,
3031- DBUS_SERVICE_UPSTART,
3032- job_path,
3033- DBUS_INTERFACE_UPSTART_JOB,
3034- "Stop",
3035- g_variant_builder_end(&builder),
3036- NULL,
3037- G_DBUS_CALL_FLAGS_NONE,
3038- -1, /* timeout: default */
3039- NULL, /* cancelable */
3040- &error);
3041-
3042- if (error != NULL) {
3043- g_warning("Unable to stop job %s app_id %s instance_id %s: %s", jobname, appname, instanceid, error->message);
3044- g_error_free(error);
3045- }
3046-
3047- g_variant_unref(stop_variant);
3048+ try {
3049+ auto registry = ubuntu::app_launch::Registry::getDefault();
3050+ auto appId = ubuntu::app_launch::AppID::find(appid);
3051+ auto app = ubuntu::app_launch::Application::create(appId, registry);
3052+
3053+ std::vector<ubuntu::app_launch::Application::URL> urivect;
3054+ for (auto i = 0; uris != nullptr && uris[i] != nullptr; i++)
3055+ urivect.emplace_back(ubuntu::app_launch::Application::URL::from_raw(uris[i]));
3056+
3057+ auto instance = app->launchTest(urivect);
3058+
3059+ if (instance) {
3060+ return TRUE;
3061+ } else {
3062+ return FALSE;
3063+ }
3064+ } catch (std::runtime_error &e) {
3065+ g_warning("Unable to start app '%s': %s", appid, e.what());
3066+ return FALSE;
3067+ }
3068 }
3069
3070 static void
3071@@ -413,49 +171,21 @@
3072 {
3073 g_return_val_if_fail(appid != NULL, FALSE);
3074
3075- GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
3076- g_return_val_if_fail(con != NULL, FALSE);
3077-
3078- gboolean found = FALSE;
3079- unsigned int i;
3080-
3081- GArray * apps = g_array_new(TRUE, TRUE, sizeof(gchar *));
3082- g_array_set_clear_func(apps, free_helper);
3083-
3084- /* Look through the click jobs and see if any match. There can
3085- only be one instance for each ID in the click world */
3086- apps_for_job(con, "application-click", apps, FALSE);
3087- for (i = 0; i < apps->len; i++) {
3088- const gchar * array_id = g_array_index(apps, const gchar *, i);
3089- if (g_strcmp0(array_id, appid) == 0) {
3090- stop_job(con, "application-click", appid, NULL);
3091- found = TRUE;
3092- break; /* There can be only one with click */
3093- }
3094- }
3095-
3096- if (apps->len > 0)
3097- g_array_remove_range(apps, 0, apps->len);
3098-
3099- /* Look through the legacy apps. Trickier because we know that there
3100- can be many instances of the legacy jobs out there, so we might
3101- have to kill more than one of them. */
3102- apps_for_job(con, "application-legacy", apps, FALSE);
3103- gchar * appiddash = g_strdup_printf("%s-", appid); /* Probably could go RegEx here, but let's start with just a prefix lookup */
3104- for (i = 0; i < apps->len; i++) {
3105- const gchar * array_id = g_array_index(apps, const gchar *, i);
3106- if (g_str_has_prefix(array_id, appiddash)) {
3107- gchar * instanceid = g_strrstr(array_id, "-");
3108- stop_job(con, "application-legacy", appid, &(instanceid[1]));
3109- found = TRUE;
3110- }
3111- }
3112- g_free(appiddash);
3113-
3114- g_array_free(apps, TRUE);
3115- g_object_unref(con);
3116-
3117- return found;
3118+ try {
3119+ auto registry = ubuntu::app_launch::Registry::getDefault();
3120+ auto appId = ubuntu::app_launch::AppID::find(appid);
3121+ auto app = ubuntu::app_launch::Application::create(appId, registry);
3122+
3123+ auto instances = app->instances();
3124+ for (auto instance : instances) {
3125+ instance->stop();
3126+ }
3127+
3128+ return TRUE;
3129+ } catch (std::runtime_error &e) {
3130+ g_warning("Unable to stop app '%s': %s", appid, e.what());
3131+ return FALSE;
3132+ }
3133 }
3134
3135 gboolean
3136@@ -489,59 +219,14 @@
3137 gchar *
3138 ubuntu_app_launch_application_log_path (const gchar * appid)
3139 {
3140- gchar * path = NULL;
3141- g_return_val_if_fail(appid != NULL, NULL);
3142-
3143- if (is_click(appid)) {
3144- gchar * appfile = g_strdup_printf("application-click-%s.log", appid);
3145- path = g_build_filename(g_get_user_cache_dir(), "upstart", appfile, NULL);
3146- g_free(appfile);
3147- return path;
3148- }
3149-
3150- if (!is_libertine(appid) && legacy_single_instance(appid)) {
3151- gchar * appfile = g_strdup_printf("application-legacy-%s-.log", appid);
3152- path = g_build_filename(g_get_user_cache_dir(), "upstart", appfile, NULL);
3153- g_free(appfile);
3154- return path;
3155- }
3156-
3157- /* If we're not single instance, we can't recreate the instance ID
3158- but if it's running we can grab it. */
3159- unsigned int i;
3160- GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
3161- g_return_val_if_fail(con != NULL, NULL);
3162-
3163- GArray * apps = g_array_new(TRUE, TRUE, sizeof(gchar *));
3164- g_array_set_clear_func(apps, free_helper);
3165-
3166- apps_for_job(con, "application-legacy", apps, FALSE);
3167- gchar * appiddash = g_strdup_printf("%s-", appid); /* Probably could go RegEx here, but let's start with just a prefix lookup */
3168- for (i = 0; i < apps->len && path == NULL; i++) {
3169- const gchar * array_id = g_array_index(apps, const gchar *, i);
3170- if (g_str_has_prefix(array_id, appiddash)) {
3171- gchar * appfile = g_strdup_printf("application-legacy-%s.log", array_id);
3172- path = g_build_filename(g_get_user_cache_dir(), "upstart", appfile, NULL);
3173- g_free(appfile);
3174- }
3175- }
3176- g_free(appiddash);
3177-
3178- g_array_free(apps, TRUE);
3179- g_object_unref(con);
3180-
3181- return path;
3182-}
3183-
3184-gboolean
3185-ubuntu_app_launch_application_info (const gchar * appid, gchar ** appdir, gchar ** appdesktop)
3186-{
3187- if (is_click(appid)) {
3188- return app_info_click(appid, appdir, appdesktop);
3189- } else if (is_libertine(appid)) {
3190- return app_info_libertine(appid, appdir, appdesktop);
3191- } else {
3192- return app_info_legacy(appid, appdir, appdesktop);
3193+ try {
3194+ auto registry = ubuntu::app_launch::Registry::getDefault();
3195+ auto appId = ubuntu::app_launch::AppID::find(appid);
3196+ auto app = ubuntu::app_launch::Application::create(appId, registry);
3197+ auto log = app->instances()[0]->logPath();
3198+ return g_strdup(log.c_str());
3199+ } catch (...) {
3200+ return NULL;
3201 }
3202 }
3203
3204@@ -1147,43 +832,6 @@
3205 g_variant_unref(instance_list);
3206 }
3207
3208-typedef struct {
3209- GArray * apps;
3210- gboolean truncate_legacy;
3211- const gchar * jobname;
3212-} apps_for_job_t;
3213-
3214-static void
3215-apps_for_job_instance (GDBusConnection * con, GVariant * props_dict, gpointer user_data)
3216-{
3217- GVariant * namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING);
3218- if (namev == NULL) {
3219- return;
3220- }
3221-
3222- apps_for_job_t * data = (apps_for_job_t *)user_data;
3223- gchar * instance_name = g_variant_dup_string(namev, NULL);
3224- g_variant_unref(namev);
3225-
3226- if (data->truncate_legacy && g_strcmp0(data->jobname, "application-legacy") == 0) {
3227- gchar * last_dash = g_strrstr(instance_name, "-");
3228- if (last_dash != NULL) {
3229- last_dash[0] = '\0';
3230- }
3231- }
3232-
3233- g_array_append_val(data->apps, instance_name);
3234-}
3235-
3236-/* Get all the instances for a given job name */
3237-static void
3238-apps_for_job (GDBusConnection * con, const gchar * jobname, GArray * apps, gboolean truncate_legacy)
3239-{
3240- apps_for_job_t data = {apps, truncate_legacy, jobname};
3241-
3242- foreach_job_instance(con, jobname, apps_for_job_instance, &data);
3243-}
3244-
3245 gchar **
3246 ubuntu_app_launch_list_running_apps (void)
3247 {
3248@@ -1208,7 +856,7 @@
3249 g_return_val_if_fail(appid != NULL, 0);
3250
3251 try {
3252- auto registry = std::make_shared<ubuntu::app_launch::Registry>();
3253+ auto registry = ubuntu::app_launch::Registry::getDefault();
3254 auto appId = ubuntu::app_launch::AppID::find(appid);
3255 auto app = ubuntu::app_launch::Application::create(appId, registry);
3256 return app->instances()[0]->primaryPid();
3257@@ -1224,7 +872,7 @@
3258 ubuntu_app_launch_get_pids (const gchar * appid)
3259 {
3260 try {
3261- auto registry = std::make_shared<ubuntu::app_launch::Registry>();
3262+ auto registry = ubuntu::app_launch::Registry::getDefault();
3263 auto appId = ubuntu::app_launch::AppID::find(appid);
3264 auto app = ubuntu::app_launch::Application::create(appId, registry);
3265 auto pids = app->instances()[0]->pids();
3266@@ -1245,7 +893,7 @@
3267 {
3268 g_return_val_if_fail(appid != NULL, FALSE);
3269 try {
3270- auto registry = std::make_shared<ubuntu::app_launch::Registry>();
3271+ auto registry = ubuntu::app_launch::Registry::getDefault();
3272 auto appId = ubuntu::app_launch::AppID::find(appid);
3273 auto app = ubuntu::app_launch::Application::create(appId, registry);
3274
3275@@ -1296,16 +944,24 @@
3276 {
3277 g_return_val_if_fail(pkg != NULL, NULL);
3278
3279- /* Check if is a libertine container */
3280- gchar * libertinepath = g_build_filename(g_get_user_cache_dir(), "libertine-container", pkg, NULL);
3281- gboolean libcontainer = g_file_test(libertinepath, G_FILE_TEST_EXISTS);
3282- g_free(libertinepath);
3283-
3284- if (libcontainer) {
3285- return libertine_triplet_to_app_id(pkg, app, ver);
3286- } else {
3287- return click_triplet_to_app_id(pkg, app, ver);
3288- }
3289+ std::string package{pkg};
3290+ std::string appname;
3291+ std::string version;
3292+
3293+ if (app != nullptr) {
3294+ appname = app;
3295+ }
3296+
3297+ if (ver != nullptr) {
3298+ version = ver;
3299+ }
3300+
3301+ auto appid = ubuntu::app_launch::AppID::discover(package, appname, version);
3302+ if (appid.empty()) {
3303+ return nullptr;
3304+ }
3305+
3306+ return g_strdup(std::string(appid).c_str());
3307 }
3308
3309 /* Print an error if we couldn't start it */
3310
3311=== modified file 'tests/exec-util-test.cc'
3312--- tests/exec-util-test.cc 2016-01-20 22:47:01 +0000
3313+++ tests/exec-util-test.cc 2016-08-04 14:02:19 +0000
3314@@ -24,6 +24,7 @@
3315 #include <libdbustest/dbus-test.h>
3316 #include <gio/gio.h>
3317 #include <libubuntu-app-launch/ubuntu-app-launch.h>
3318+#include <libubuntu-app-launch/registry.h>
3319
3320 class ExecUtil : public ::testing::Test
3321 {
3322@@ -79,6 +80,7 @@
3323
3324 virtual void TearDown() {
3325 ubuntu_app_launch_observer_delete_app_starting(starting_cb, NULL);
3326+ ubuntu::app_launch::Registry::clearDefault();
3327
3328 g_clear_object(&mock);
3329 g_clear_object(&service);
3330@@ -130,8 +132,11 @@
3331 /* Test the variable */
3332 auto varfunc = enums[var];
3333 EXPECT_NE(nullptr, varfunc);
3334- if (varfunc)
3335+ if (varfunc) {
3336 varfunc(value);
3337+ } else {
3338+ g_warning("Unable to find function for '%s'", var);
3339+ }
3340
3341 /* Mark it as found */
3342 env_found[var] = true;
3343@@ -143,6 +148,9 @@
3344
3345 for(auto enumval : enums) {
3346 EXPECT_TRUE(env_found[enumval.first]);
3347+ if (!env_found[enumval.first]) {
3348+ g_warning("Unable to find enum %s", enumval.first.c_str());
3349+ }
3350 }
3351 }
3352 };
3353@@ -177,8 +185,10 @@
3354 EXPECT_STREQ("com.test.good_application_1.2.3", value); }},
3355 {"APP_LAUNCHER_PID", [](const gchar * value) {
3356 EXPECT_EQ(getpid(), atoi(value)); }},
3357- {"APP_DESKTOP_FILE_PATH", [](const gchar * value) {
3358- EXPECT_STREQ(APP_DIR "/application.desktop", value); }},
3359+ /* {"APP_DESKTOP_FILE_PATH", [](const gchar * value) {
3360+ EXPECT_STREQ(APP_DIR "/application.desktop", value); }}, */
3361+ {"APP_XMIR_ENABLE", [](const gchar * value) {
3362+ EXPECT_STREQ("0", value); }},
3363 });
3364
3365 #undef APP_DIR
3366@@ -189,8 +199,8 @@
3367 StartCheckEnv("foo", {
3368 {"APP_EXEC", [](const gchar * value) {
3369 EXPECT_STREQ("foo", value); }},
3370- {"APP_DESKTOP_FILE_PATH", [](const gchar * value) {
3371- EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/foo.desktop", value); }},
3372+ /* {"APP_DESKTOP_FILE_PATH", [](const gchar * value) {
3373+ EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/foo.desktop", value); }}, */
3374 {"APP_EXEC_POLICY", [](const gchar * value) {
3375 EXPECT_STREQ("unconfined", value); }},
3376 {"APP_ID", [](const gchar * value) {
3377@@ -198,6 +208,8 @@
3378 {"INSTANCE_ID", nocheck},
3379 {"APP_LAUNCHER_PID", [](const gchar * value) {
3380 EXPECT_EQ(getpid(), atoi(value)); }},
3381+ {"APP_XMIR_ENABLE", [](const gchar * value) {
3382+ EXPECT_STREQ("0", value); }},
3383 });
3384 }
3385
3386@@ -206,8 +218,8 @@
3387 StartCheckEnv("xmir", {
3388 {"APP_EXEC", [](const gchar * value) {
3389 EXPECT_STREQ("xfoo", value); }},
3390- {"APP_DESKTOP_FILE_PATH", [](const gchar * value) {
3391- EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/xmir.desktop", value); }},
3392+ /* {"APP_DESKTOP_FILE_PATH", [](const gchar * value) {
3393+ EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/xmir.desktop", value); }}, */
3394 {"APP_EXEC_POLICY", [](const gchar * value) {
3395 EXPECT_STREQ("unconfined", value); }},
3396 {"APP_ID", [](const gchar * value) {
3397@@ -225,8 +237,8 @@
3398 StartCheckEnv("noxmir", {
3399 {"APP_EXEC", [](const gchar * value) {
3400 EXPECT_STREQ("noxmir", value); }},
3401- {"APP_DESKTOP_FILE_PATH", [](const gchar * value) {
3402- EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/noxmir.desktop", value); }},
3403+ /* {"APP_DESKTOP_FILE_PATH", [](const gchar * value) {
3404+ EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/noxmir.desktop", value); }}, */
3405 {"APP_EXEC_POLICY", [](const gchar * value) {
3406 EXPECT_STREQ("unconfined", value); }},
3407 {"APP_ID", [](const gchar * value) {
3408@@ -255,7 +267,7 @@
3409 {"APP_ID", [](const gchar * value) {
3410 EXPECT_STREQ("com.test.mir_mir_1", value); }},
3411 {"APP_LAUNCHER_PID", nocheck},
3412- {"APP_DESKTOP_FILE_PATH", nocheck},
3413+ /* {"APP_DESKTOP_FILE_PATH", nocheck}, */
3414 {"APP_XMIR_ENABLE", [](const gchar * value) {
3415 EXPECT_STREQ("1", value); }},
3416 });
3417@@ -277,7 +289,7 @@
3418 {"APP_ID", [](const gchar * value) {
3419 EXPECT_STREQ("com.test.mir_nomir_1", value); }},
3420 {"APP_LAUNCHER_PID", nocheck},
3421- {"APP_DESKTOP_FILE_PATH", nocheck},
3422+ /* {"APP_DESKTOP_FILE_PATH", nocheck}, */
3423 {"APP_XMIR_ENABLE", [](const gchar * value) {
3424 EXPECT_STREQ("0", value); }},
3425 });
3426
3427=== modified file 'tests/libual-cpp-test.cc'
3428--- tests/libual-cpp-test.cc 2016-08-04 14:02:18 +0000
3429+++ tests/libual-cpp-test.cc 2016-08-04 14:02:19 +0000
3430@@ -25,6 +25,7 @@
3431
3432 #include "mir-mock.h"
3433 #include <gio/gio.h>
3434+#include <glib/gstdio.h>
3435 #include <gtest/gtest.h>
3436 #include <zeitgeist.h>
3437
3438@@ -342,7 +343,7 @@
3439 }
3440 };
3441
3442-TEST_F(LibUAL, StartApplication)
3443+TEST_F(LibUAL, StartClickApplication)
3444 {
3445 DbusTestDbusMockObject* obj =
3446 dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL);
3447@@ -399,7 +400,7 @@
3448 return;
3449 }
3450
3451-TEST_F(LibUAL, StartApplicationTest)
3452+TEST_F(LibUAL, StartClickApplicationTest)
3453 {
3454 DbusTestDbusMockObject* obj =
3455 dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL);
3456@@ -427,7 +428,7 @@
3457 g_variant_unref(env);
3458 }
3459
3460-TEST_F(LibUAL, StopApplication)
3461+TEST_F(LibUAL, StopClickApplication)
3462 {
3463 DbusTestDbusMockObject* obj =
3464 dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL);
3465@@ -456,15 +457,15 @@
3466 std::string(CMAKE_SOURCE_DIR "/libertine-data/upstart/application-click-com.test.good_application_1.2.3.log"),
3467 app->instances()[0]->logPath());
3468
3469- appid = ubuntu::app_launch::AppID::find("single");
3470+ appid = ubuntu::app_launch::AppID::find(registry, "single");
3471 app = ubuntu::app_launch::Application::create(appid, registry);
3472
3473- ASSERT_LT(0, app->instances().size());
3474+ ASSERT_LT(0, app->instances().size());
3475
3476 EXPECT_EQ(std::string(CMAKE_SOURCE_DIR "/libertine-data/upstart/application-legacy-single-.log"),
3477 app->instances()[0]->logPath());
3478
3479- appid = ubuntu::app_launch::AppID::find("multiple");
3480+ appid = ubuntu::app_launch::AppID::find(registry, "multiple");
3481 app = ubuntu::app_launch::Application::create(appid, registry);
3482
3483 EXPECT_EQ(std::string(CMAKE_SOURCE_DIR "/libertine-data/upstart/application-legacy-multiple-2342345.log"),
3484@@ -486,9 +487,10 @@
3485 EXPECT_TRUE(app->instances()[0]->hasPid(300));
3486
3487 /* Check primary pid, which comes from Upstart */
3488+ EXPECT_TRUE(app->instances()[0]->isRunning());
3489 EXPECT_EQ(getpid(), app->instances()[0]->primaryPid());
3490
3491- auto multiappid = ubuntu::app_launch::AppID::find("multiple");
3492+ auto multiappid = ubuntu::app_launch::AppID::find(registry, "multiple");
3493 auto multiapp = ubuntu::app_launch::Application::create(multiappid, registry);
3494 auto instances = multiapp->instances();
3495 ASSERT_LT(0, instances.size());
3496@@ -520,7 +522,7 @@
3497 ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(cgmock, cgobject, NULL));
3498
3499 /* Legacy Single Instance */
3500- auto singleappid = ubuntu::app_launch::AppID::find("single");
3501+ auto singleappid = ubuntu::app_launch::AppID::find(registry, "single");
3502 auto singleapp = ubuntu::app_launch::Application::create(singleappid, registry);
3503
3504 ASSERT_LT(0, singleapp->instances().size());
3505@@ -549,50 +551,53 @@
3506
3507 /* Test with current-user-version, should return the version in the manifest */
3508 EXPECT_EQ("com.test.good_application_1.2.3",
3509- (std::string)ubuntu::app_launch::AppID::discover("com.test.good", "application"));
3510+ (std::string)ubuntu::app_launch::AppID::discover(registry, "com.test.good", "application"));
3511
3512 /* Test with version specified, shouldn't even read the manifest */
3513 EXPECT_EQ("com.test.good_application_1.2.4",
3514- (std::string)ubuntu::app_launch::AppID::discover("com.test.good", "application", "1.2.4"));
3515+ (std::string)ubuntu::app_launch::AppID::discover(registry, "com.test.good", "application", "1.2.4"));
3516
3517 /* Test with out a version or app, should return the version in the manifest */
3518- EXPECT_EQ("com.test.good_application_1.2.3", (std::string)ubuntu::app_launch::AppID::discover(
3519- "com.test.good", "first-listed-app", "current-user-version"));
3520+ EXPECT_EQ("com.test.good_application_1.2.3",
3521+ (std::string)ubuntu::app_launch::AppID::discover(registry, "com.test.good", "first-listed-app",
3522+ "current-user-version"));
3523
3524 /* Make sure we can select the app from a list correctly */
3525 EXPECT_EQ("com.test.multiple_first_1.2.3",
3526 (std::string)ubuntu::app_launch::AppID::discover(
3527- "com.test.multiple", ubuntu::app_launch::AppID::ApplicationWildcard::FIRST_LISTED));
3528- EXPECT_EQ("com.test.multiple_first_1.2.3", (std::string)ubuntu::app_launch::AppID::discover("com.test.multiple"));
3529+ registry, "com.test.multiple", ubuntu::app_launch::AppID::ApplicationWildcard::FIRST_LISTED));
3530+ EXPECT_EQ("com.test.multiple_first_1.2.3",
3531+ (std::string)ubuntu::app_launch::AppID::discover(registry, "com.test.multiple"));
3532 EXPECT_EQ("com.test.multiple_fifth_1.2.3",
3533 (std::string)ubuntu::app_launch::AppID::discover(
3534- "com.test.multiple", ubuntu::app_launch::AppID::ApplicationWildcard::LAST_LISTED));
3535+ registry, "com.test.multiple", ubuntu::app_launch::AppID::ApplicationWildcard::LAST_LISTED));
3536 EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover(
3537- "com.test.multiple", ubuntu::app_launch::AppID::ApplicationWildcard::ONLY_LISTED));
3538+ registry, "com.test.multiple", ubuntu::app_launch::AppID::ApplicationWildcard::ONLY_LISTED));
3539 EXPECT_EQ("com.test.good_application_1.2.3",
3540 (std::string)ubuntu::app_launch::AppID::discover(
3541- "com.test.good", ubuntu::app_launch::AppID::ApplicationWildcard::ONLY_LISTED));
3542+ registry, "com.test.good", ubuntu::app_launch::AppID::ApplicationWildcard::ONLY_LISTED));
3543
3544 /* A bunch that should be NULL */
3545- EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover("com.test.no-hooks"));
3546- EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover("com.test.no-json"));
3547- EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover("com.test.no-object"));
3548- EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover("com.test.no-version"));
3549+ EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover(registry, "com.test.no-hooks"));
3550+ EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover(registry, "com.test.no-json"));
3551+ EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover(registry, "com.test.no-object"));
3552+ EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover(registry, "com.test.no-version"));
3553
3554 /* Libertine tests */
3555- EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover("container-name"));
3556- EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover("container-name", "not-exist"));
3557- EXPECT_EQ("container-name_test_0.0", (std::string)ubuntu::app_launch::AppID::discover("container-name", "test"));
3558+ EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover(registry, "container-name"));
3559+ EXPECT_EQ("", (std::string)ubuntu::app_launch::AppID::discover(registry, "container-name", "not-exist"));
3560+ EXPECT_EQ("container-name_test_0.0",
3561+ (std::string)ubuntu::app_launch::AppID::discover(registry, "container-name", "test"));
3562 EXPECT_EQ("container-name_user-app_0.0",
3563- (std::string)ubuntu::app_launch::AppID::discover("container-name", "user-app"));
3564+ (std::string)ubuntu::app_launch::AppID::discover(registry, "container-name", "user-app"));
3565 }
3566
3567 TEST_F(LibUAL, AppIdParse)
3568 {
3569 EXPECT_FALSE(ubuntu::app_launch::AppID::parse("com.ubuntu.test_test_123").empty());
3570- EXPECT_FALSE(ubuntu::app_launch::AppID::find("inkscape").empty());
3571+ EXPECT_FALSE(ubuntu::app_launch::AppID::find(registry, "inkscape").empty());
3572 EXPECT_FALSE(ubuntu::app_launch::AppID::parse("chatter.robert-ancell_chatter_2").empty());
3573- EXPECT_FALSE(ubuntu::app_launch::AppID::find("chatter.robert-ancell_chatter").empty());
3574+ EXPECT_FALSE(ubuntu::app_launch::AppID::find(registry, "chatter.robert-ancell_chatter").empty());
3575
3576 auto id = ubuntu::app_launch::AppID::parse("com.ubuntu.test_test_123");
3577
3578@@ -960,7 +965,7 @@
3579 dbus_test_dbus_mock_get_object(mock, "/com/test/application_legacy", "com.ubuntu.Upstart0_6.Job", NULL);
3580
3581 /* Check for a single-instance app */
3582- auto singleappid = ubuntu::app_launch::AppID::find("single");
3583+ auto singleappid = ubuntu::app_launch::AppID::find(registry, "single");
3584 auto singleapp = ubuntu::app_launch::Application::create(singleappid, registry);
3585
3586 singleapp->launch();
3587@@ -985,7 +990,7 @@
3588 ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL));
3589
3590 /* Check for a multi-instance app */
3591- auto multipleappid = ubuntu::app_launch::AppID::find("multiple");
3592+ auto multipleappid = ubuntu::app_launch::AppID::find(registry, "multiple");
3593 auto multipleapp = ubuntu::app_launch::Application::create(multipleappid, registry);
3594
3595 multipleapp->launch();
3596@@ -1462,7 +1467,7 @@
3597 signal_increment, &resumed_count, nullptr);
3598
3599 /* Get our app object */
3600- auto appid = ubuntu::app_launch::AppID::find("com.test.good_application_1.2.3");
3601+ auto appid = ubuntu::app_launch::AppID::find(registry, "com.test.good_application_1.2.3");
3602 auto app = ubuntu::app_launch::Application::create(appid, registry);
3603
3604 ASSERT_EQ(1, app->instances().size());
3605@@ -1572,7 +1577,7 @@
3606 dbus_test_task_get_state(DBUS_TEST_TASK(zgmock)) != DBUS_TEST_TASK_STATE_RUNNING);
3607
3608 /* Get our app object */
3609- auto appid = ubuntu::app_launch::AppID::find("com.test.good_application_1.2.3");
3610+ auto appid = ubuntu::app_launch::AppID::find(registry, "com.test.good_application_1.2.3");
3611 auto app = ubuntu::app_launch::Application::create(appid, registry);
3612
3613 ASSERT_EQ(1, app->instances().size());
3614@@ -1657,7 +1662,7 @@
3615 } while (dbus_test_task_get_state(DBUS_TEST_TASK(cgmock2)) != DBUS_TEST_TASK_STATE_RUNNING);
3616
3617 /* Get our app object */
3618- auto appid = ubuntu::app_launch::AppID::find("com.test.good_application_1.2.3");
3619+ auto appid = ubuntu::app_launch::AppID::find(registry, "com.test.good_application_1.2.3");
3620 auto app = ubuntu::app_launch::Application::create(appid, registry);
3621
3622 ASSERT_EQ(1, app->instances().size());
3623@@ -1868,7 +1873,7 @@
3624 EXPECT_EQ("Application", app->info()->name().value());
3625
3626 /* Correct values from a legacy */
3627- auto barid = ubuntu::app_launch::AppID::find("bar");
3628+ auto barid = ubuntu::app_launch::AppID::find(registry, "bar");
3629 EXPECT_THROW(ubuntu::app_launch::Application::create(barid, registry), std::runtime_error);
3630
3631 /* Correct values for libertine */
3632
3633=== modified file 'tests/list-apps.cpp'
3634--- tests/list-apps.cpp 2016-08-04 14:02:18 +0000
3635+++ tests/list-apps.cpp 2016-08-04 14:02:19 +0000
3636@@ -135,7 +135,7 @@
3637 auto registry = std::make_shared<ubuntu::app_launch::Registry>();
3638 auto apps = ubuntu::app_launch::app_impls::Legacy::list(registry);
3639
3640- EXPECT_EQ(1, apps.size());
3641+ EXPECT_EQ(0, apps.size());
3642 }
3643
3644 TEST_F(ListApps, ListLibertine)
3645@@ -156,5 +156,5 @@
3646 /* Get all the apps */
3647 auto apps = ubuntu::app_launch::Registry::installedApps(registry);
3648
3649- EXPECT_EQ(14, apps.size());
3650+ EXPECT_EQ(13, apps.size());
3651 }

Subscribers

People subscribed via source and target branches