Merge lp:~ted/ubuntu-app-launch/snappy-backend-no-snap into lp:ubuntu-app-launch/16.10
- snappy-backend-no-snap
- Merge into trunk.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 |
Related bugs: |
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.
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote : | # |
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 | } |
FAILED: Continuous integration, rev:352 /code.launchpad .net/~ted/ ubuntu- app-launch/ snappy- backend- no-snap/ +merge/ 301966/ +edit-commit- message
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:/
https:/ /jenkins. canonical. com/unity- api-1/job/ lp-ubuntu- app-launch- ci/18/ /jenkins. canonical. com/unity- api-1/job/ build/277/ console /jenkins. canonical. com/unity- api-1/job/ build-0- fetch/283 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= vivid+overlay/ 217 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= xenial+ overlay/ 217 /jenkins. canonical. com/unity- api-1/job/ build-1- sourcepkg/ release= yakkety/ 217 /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= vivid+overlay/ 146/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= xenial+ overlay/ 146/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=amd64, release= yakkety/ 146/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= vivid+overlay/ 146/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= xenial+ overlay/ 146/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=armhf, release= yakkety/ 146/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= vivid+overlay/ 146/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= xenial+ overlay/ 146/console /jenkins. canonical. com/unity- api-1/job/ build-2- binpkg/ arch=i386, release= yakkety/ 146/console
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild: /jenkins. canonical. com/unity- api-1/job/ lp-ubuntu- app-launch- ci/18/rebuild
https:/