Merge lp:~ted/ubuntu-app-launch/app-object-signals into lp:ubuntu-app-launch
- app-object-signals
- Merge into trunk.17.04
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Ted Gould | ||||
Approved revision: | 314 | ||||
Merged at revision: | 275 | ||||
Proposed branch: | lp:~ted/ubuntu-app-launch/app-object-signals | ||||
Merge into: | lp:ubuntu-app-launch | ||||
Diff against target: |
3388 lines (+1673/-939) 24 files modified
libubuntu-app-launch/application-impl-base.cpp (+15/-16) libubuntu-app-launch/application.cpp (+5/-0) libubuntu-app-launch/helper.h (+12/-0) libubuntu-app-launch/libubuntu-app-launch.map (+1/-0) libubuntu-app-launch/registry-impl.cpp (+565/-29) libubuntu-app-launch/registry-impl.h (+88/-11) libubuntu-app-launch/registry.cpp (+49/-6) libubuntu-app-launch/registry.h (+123/-14) libubuntu-app-launch/ubuntu-app-launch.cpp (+298/-436) tests/CMakeLists.txt (+1/-0) tests/failure-test.cc (+123/-96) tests/libual-cpp-test.cc (+192/-141) tools/CMakeLists.txt (+21/-2) tools/ubuntu-app-info.cpp (+18/-9) tools/ubuntu-app-launch.cpp (+56/-68) tools/ubuntu-app-list-pids.cpp (+7/-3) tools/ubuntu-app-list.cpp (+1/-1) tools/ubuntu-app-pid.cpp (+8/-4) tools/ubuntu-app-stop.cpp (+7/-3) tools/ubuntu-app-triplet.cpp (+1/-1) tools/ubuntu-app-watch.cpp (+61/-88) tools/ubuntu-helper-list.cpp (+1/-1) tools/ubuntu-helper-start.cpp (+10/-5) tools/ubuntu-helper-stop.cpp (+10/-5) |
||||
To merge this branch: | bzr merge lp:~ted/ubuntu-app-launch/app-object-signals | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
dobey (community) | Needs Fixing | ||
Charles Kerr (community) | Approve | ||
unity-api-1-bot | continuous-integration | Needs Fixing | |
PS Jenkins bot | continuous-integration | Pending | |
Review via email: mp+310230@code.launchpad.net |
This proposal supersedes a proposal from 2016-05-16.
Commit message
Change signals into C++ core::signal objects
Description of the change
This branch, on its own, is reshuffling the chairs on the deck of the Titanic. We're mostly setting up the branches to abstract out Upstart and Systemd but need to get the signals converted first. This is a "small" step on that road.
All of the signals now come from the Registry and then the C signals use the default registry to register against. The C signals also keep track of context as the previous C API was GLib based and that's what GLib callers would expect. The C++ signals require marshalling to the appropriate thread if needed.
There is also the addition of the manager interface, but we're not yet in this branch actually blocking the startup of apps based on it. Though the interface is designed to do that in the future.
Lastly, the C++ signals also have a space for the instance, but the signals would have to be changed. Saving that for the next branch to avoid complicating this one as little as possible. There are several TODOs in the code because of this.
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:234
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:/
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : Posted in a previous version of this proposal | # |
FAILED: Continuous integration, rev:235
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:/
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:276
https:/
Executed test runs:
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:276
https:/
Executed test runs:
FAILURE: 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:
https:/
Michael Terry (mterry) wrote : | # |
Ted asked me to look at this from a "is this API suitable for Unity8" perspective.
It seems fine to me. Mostly we are interested in delaying/stopping an app from starting if we're not in the right context (like non-Touch app on a phone). This API looks sufficient for that.
A couple notes though:
- Application:
- There are a few "singal" typos in doc strings.
- Also in doc strings, you might want to clarify behavior around delayed replies. Like if the manager doesn't immediately get back to UAL, is there a timeout? What if another request comes in while the manager is considering what to do -- I'm assuming UAL gives that to the manager and lets it decide, rather than denying the second one quietly? This information would help me know how carefully I have to write the signal handlers.
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:277
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:278
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
FAILURE: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
PASSED: Continuous integration, rev:279
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
SUCCESS: https:/
deb: https:/
Click here to trigger a rebuild:
https:/
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:280
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Charles Kerr (charlesk) wrote : | # |
Got about 1000 lines in, review part 1 inline
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:280
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Ted Gould (ted) : | # |
- 281. By Ted Gould
-
Remove some of the sing song part of the comments
- 282. By Ted Gould
-
Additional comment on lifecycle of replies
- 283. By Ted Gould
-
Zesty formatting tools diffs
- 284. By Ted Gould
-
Curly init
- 285. By Ted Gould
-
Make sure to check for a nullappid or error for g_variant_get()
- 286. By Ted Gould
-
Names of the parameters for clarity
- 287. By Ted Gould
-
Moar auto!
- 288. By Ted Gould
-
Don't specify returning void explicitly
- 289. By Ted Gould
-
Use static_cast() for void* casts
- 290. By Ted Gould
-
Don't spell well
- 291. By Ted Gould
-
Make sure to check for a valid registry
- 292. By Ted Gould
-
Comment out unused variables
- 293. By Ted Gould
-
Sometimes life would be better if it was more constant
- 294. By Ted Gould
-
Me no spell good
- 295. By Ted Gould
-
auto auto auto
- 296. By Ted Gould
-
Some 'NULL's crept in
- 297. By Ted Gould
-
More auto's with GVariants
- 298. By Ted Gould
-
Make params constant
- 299. By Ted Gould
-
Change setManager to have const& parameters
- 300. By Ted Gould
-
Fix the API so that the signal callbacks take pointers
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:300
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Charles Kerr (charlesk) wrote : | # |
Part 2/2
Ted Gould (ted) : | # |
- 301. By Ted Gould
-
Note it is on the UAL thread only
- 302. By Ted Gould
-
Save some stack data with this context
- 303. By Ted Gould
-
Formatting fix
- 304. By Ted Gould
-
Use an ensure_cmanager() helper to remove duplicate code
- 305. By Ted Gould
-
Putting all the map handling code in a couple templates
- 306. By Ted Gould
-
Pull out the request code into individual functions
- 307. By Ted Gould
-
Rename a function and add comments
- 308. By Ted Gould
-
Expand the usage of observer_delete
- 309. By Ted Gould
-
Factor out pause/resume commonality
- 310. By Ted Gould
-
I've been overrided by charles
Ted Gould (ted) wrote : | # |
$ bzr diff -r 281..310 | wc -l
1418
Ted Gould (ted) wrote : | # |
I think that after this silo lands we need to put ubuntu-
unity-api-1-bot (unity-api-1-bot) wrote : | # |
FAILED: Continuous integration, rev:310
https:/
Executed test runs:
FAILURE: https:/
SUCCESS: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
FAILURE: https:/
Click here to trigger a rebuild:
https:/
Charles Kerr (charlesk) wrote : | # |
Whew, going through and looking at the full diff cold again this morning, I agree wrt (a) running this through the autoformatter, some of these lines are super wide (b) following standard procedure of doing that in a standalone branch with no other changes
Thanks for the changes. This branch is insane on its own but as a step to the followup branches it makes sense.
dobey (dobey) wrote : | # |
Too many totally unrelated style changes, including addition of auto-formatting of unrelated code.
Introduces failing tests.
All actual new code in this branch appears to simply be moved around to other files in another branch which depends on this one.
Changed copyright years are mostly wrong.
Really needs to be broken up better, and have passing tests.
Preview Diff
1 | === modified file 'libubuntu-app-launch/application-impl-base.cpp' | |||
2 | --- libubuntu-app-launch/application-impl-base.cpp 2016-11-10 15:34:52 +0000 | |||
3 | +++ libubuntu-app-launch/application-impl-base.cpp 2017-01-24 04:21:42 +0000 | |||
4 | @@ -556,22 +556,21 @@ | |||
5 | 556 | std::array<const char*, 4> args = {OOM_HELPER, pidstr.c_str(), oomstr.c_str(), nullptr}; | 556 | std::array<const char*, 4> args = {OOM_HELPER, pidstr.c_str(), oomstr.c_str(), nullptr}; |
6 | 557 | 557 | ||
7 | 558 | g_debug("Excuting OOM Helper (pid: %d, score: %d): %s", int(pid), int(oomvalue), | 558 | g_debug("Excuting OOM Helper (pid: %d, score: %d): %s", int(pid), int(oomvalue), |
24 | 559 | std::accumulate(args.begin(), args.end(), std::string{}, | 559 | std::accumulate(args.begin(), args.end(), std::string{}, [](const std::string& instr, |
25 | 560 | [](const std::string& instr, const char* output) -> std::string { | 560 | const char* output) -> std::string { |
26 | 561 | if (instr.empty()) | 561 | if (instr.empty()) |
27 | 562 | { | 562 | { |
28 | 563 | return output; | 563 | return output; |
29 | 564 | } | 564 | } |
30 | 565 | else if (output != nullptr) | 565 | else if (output != nullptr) |
31 | 566 | { | 566 | { |
32 | 567 | return instr + " " + std::string(output); | 567 | return instr + " " + std::string(output); |
33 | 568 | } | 568 | } |
34 | 569 | else | 569 | else |
35 | 570 | { | 570 | { |
36 | 571 | return instr; | 571 | return instr; |
37 | 572 | } | 572 | } |
38 | 573 | }) | 573 | }).c_str()); |
23 | 574 | .c_str()); | ||
39 | 575 | 574 | ||
40 | 576 | g_spawn_async(nullptr, /* working dir */ | 575 | g_spawn_async(nullptr, /* working dir */ |
41 | 577 | (char**)(args.data()), /* args */ | 576 | (char**)(args.data()), /* args */ |
42 | 578 | 577 | ||
43 | === modified file 'libubuntu-app-launch/application.cpp' | |||
44 | --- libubuntu-app-launch/application.cpp 2016-08-26 17:33:34 +0000 | |||
45 | +++ libubuntu-app-launch/application.cpp 2017-01-24 04:21:42 +0000 | |||
46 | @@ -46,6 +46,11 @@ | |||
47 | 46 | throw std::runtime_error("AppID is empty"); | 46 | throw std::runtime_error("AppID is empty"); |
48 | 47 | } | 47 | } |
49 | 48 | 48 | ||
50 | 49 | if (!registry || !registry->impl) | ||
51 | 50 | { | ||
52 | 51 | throw std::runtime_error("Invalid registry object"); | ||
53 | 52 | } | ||
54 | 53 | |||
55 | 49 | if (app_impls::Click::hasAppId(appid, registry)) | 54 | if (app_impls::Click::hasAppId(appid, registry)) |
56 | 50 | { | 55 | { |
57 | 51 | return std::make_shared<app_impls::Click>(appid, registry); | 56 | return std::make_shared<app_impls::Click>(appid, registry); |
58 | 52 | 57 | ||
59 | === modified file 'libubuntu-app-launch/helper.h' | |||
60 | --- libubuntu-app-launch/helper.h 2016-06-09 14:55:34 +0000 | |||
61 | +++ libubuntu-app-launch/helper.h 2017-01-24 04:21:42 +0000 | |||
62 | @@ -62,6 +62,12 @@ | |||
63 | 62 | */ | 62 | */ |
64 | 63 | class Helper | 63 | class Helper |
65 | 64 | { | 64 | { |
66 | 65 | /* | ||
67 | 66 | protected: | ||
68 | 67 | Helper() = default; | ||
69 | 68 | virtual ~Helper() = default; | ||
70 | 69 | TODO: Next ABI break */ | ||
71 | 70 | |||
72 | 65 | public: | 71 | public: |
73 | 66 | /** \private */ | 72 | /** \private */ |
74 | 67 | struct TypeTag; | 73 | struct TypeTag; |
75 | @@ -87,6 +93,12 @@ | |||
76 | 87 | /** Running instance of a a Helper */ | 93 | /** Running instance of a a Helper */ |
77 | 88 | class Instance | 94 | class Instance |
78 | 89 | { | 95 | { |
79 | 96 | /* | ||
80 | 97 | protected: | ||
81 | 98 | Instance() = default; | ||
82 | 99 | virtual ~Instance() = default; | ||
83 | 100 | TODO: Next ABI break */ | ||
84 | 101 | |||
85 | 90 | public: | 102 | public: |
86 | 91 | /** Check to see if this instance is running */ | 103 | /** Check to see if this instance is running */ |
87 | 92 | virtual bool isRunning() = 0; | 104 | virtual bool isRunning() = 0; |
88 | 93 | 105 | ||
89 | === modified file 'libubuntu-app-launch/libubuntu-app-launch.map' | |||
90 | --- libubuntu-app-launch/libubuntu-app-launch.map 2016-05-19 16:24:11 +0000 | |||
91 | +++ libubuntu-app-launch/libubuntu-app-launch.map 2017-01-24 04:21:42 +0000 | |||
92 | @@ -14,6 +14,7 @@ | |||
93 | 14 | ubuntu::app_launch::Helper::*; | 14 | ubuntu::app_launch::Helper::*; |
94 | 15 | typeinfo?for?ubuntu::app_launch::Helper; | 15 | typeinfo?for?ubuntu::app_launch::Helper; |
95 | 16 | typeinfo?name?for?ubuntu::app_launch::Helper; | 16 | typeinfo?name?for?ubuntu::app_launch::Helper; |
96 | 17 | ubuntu::app_launch::operator*; | ||
97 | 17 | ubuntu::app_launch::oom::*; | 18 | ubuntu::app_launch::oom::*; |
98 | 18 | }; | 19 | }; |
99 | 19 | local: | 20 | local: |
100 | 20 | 21 | ||
101 | === modified file 'libubuntu-app-launch/registry-impl.cpp' | |||
102 | --- libubuntu-app-launch/registry-impl.cpp 2016-11-10 15:38:50 +0000 | |||
103 | +++ libubuntu-app-launch/registry-impl.cpp 2017-01-24 04:21:42 +0000 | |||
104 | @@ -20,6 +20,7 @@ | |||
105 | 20 | #include "registry-impl.h" | 20 | #include "registry-impl.h" |
106 | 21 | #include "application-icon-finder.h" | 21 | #include "application-icon-finder.h" |
107 | 22 | #include <cgmanager/cgmanager.h> | 22 | #include <cgmanager/cgmanager.h> |
108 | 23 | #include <regex> | ||
109 | 23 | #include <upstart.h> | 24 | #include <upstart.h> |
110 | 24 | 25 | ||
111 | 25 | namespace ubuntu | 26 | namespace ubuntu |
112 | @@ -36,13 +37,29 @@ | |||
113 | 36 | zgLog_.reset(); | 37 | zgLog_.reset(); |
114 | 37 | cgManager_.reset(); | 38 | cgManager_.reset(); |
115 | 38 | 39 | ||
116 | 40 | auto dohandle = [&](guint& handle) { | ||
117 | 41 | if (handle != 0) | ||
118 | 42 | { | ||
119 | 43 | g_dbus_connection_signal_unsubscribe(_dbus.get(), handle); | ||
120 | 44 | handle = 0; | ||
121 | 45 | } | ||
122 | 46 | }; | ||
123 | 47 | |||
124 | 48 | dohandle(handle_appStarted); | ||
125 | 49 | dohandle(handle_appStopped); | ||
126 | 50 | dohandle(handle_appFailed); | ||
127 | 51 | dohandle(handle_appPaused); | ||
128 | 52 | dohandle(handle_appResumed); | ||
129 | 53 | dohandle(handle_managerSignalFocus); | ||
130 | 54 | dohandle(handle_managerSignalResume); | ||
131 | 55 | dohandle(handle_managerSignalStarting); | ||
132 | 56 | |||
133 | 39 | if (_dbus) | 57 | if (_dbus) |
134 | 40 | g_dbus_connection_flush_sync(_dbus.get(), nullptr, nullptr); | 58 | g_dbus_connection_flush_sync(_dbus.get(), nullptr, nullptr); |
135 | 41 | _dbus.reset(); | 59 | _dbus.reset(); |
136 | 42 | }) | 60 | }) |
138 | 43 | , _registry(registry) | 61 | , _registry{registry} |
139 | 44 | , _iconFinders() | 62 | , _iconFinders() |
140 | 45 | // _manager(nullptr) | ||
141 | 46 | { | 63 | { |
142 | 47 | auto cancel = thread.getCancellable(); | 64 | auto cancel = thread.getCancellable(); |
143 | 48 | _dbus = thread.executeOnThread<std::shared_ptr<GDBusConnection>>([cancel]() { | 65 | _dbus = thread.executeOnThread<std::shared_ptr<GDBusConnection>>([cancel]() { |
144 | @@ -139,6 +156,7 @@ | |||
145 | 139 | 156 | ||
146 | 140 | auto node = json_node_alloc(); | 157 | auto node = json_node_alloc(); |
147 | 141 | json_node_init_object(node, mani); | 158 | json_node_init_object(node, mani); |
148 | 159 | json_object_unref(mani); | ||
149 | 142 | 160 | ||
150 | 143 | auto retval = std::shared_ptr<JsonObject>(json_node_dup_object(node), json_object_unref); | 161 | auto retval = std::shared_ptr<JsonObject>(json_node_dup_object(node), json_object_unref); |
151 | 144 | 162 | ||
152 | @@ -168,9 +186,9 @@ | |||
153 | 168 | } | 186 | } |
154 | 169 | 187 | ||
155 | 170 | std::list<AppID::Package> list; | 188 | std::list<AppID::Package> list; |
157 | 171 | for (GList* item = pkgs; item != NULL; item = g_list_next(item)) | 189 | for (GList* item = pkgs; item != nullptr; item = g_list_next(item)) |
158 | 172 | { | 190 | { |
160 | 173 | auto pkgobj = reinterpret_cast<gchar*>(item->data); | 191 | auto pkgobj = static_cast<gchar*>(item->data); |
161 | 174 | if (pkgobj) | 192 | if (pkgobj) |
162 | 175 | { | 193 | { |
163 | 176 | list.emplace_back(AppID::Package::from_raw(pkgobj)); | 194 | list.emplace_back(AppID::Package::from_raw(pkgobj)); |
164 | @@ -269,7 +287,7 @@ | |||
165 | 269 | 287 | ||
166 | 270 | GVariant* vtpids = g_dbus_connection_call_sync( | 288 | GVariant* vtpids = g_dbus_connection_call_sync( |
167 | 271 | lmanager.get(), /* connection */ | 289 | lmanager.get(), /* connection */ |
169 | 272 | name, /* bus name for direct connection is NULL */ | 290 | name, /* bus name for direct connection is nullptr */ |
170 | 273 | "/org/linuxcontainers/cgmanager", /* object */ | 291 | "/org/linuxcontainers/cgmanager", /* object */ |
171 | 274 | "org.linuxcontainers.cgmanager0_0", /* interface */ | 292 | "org.linuxcontainers.cgmanager0_0", /* interface */ |
172 | 275 | "GetTasksRecursive", /* method */ | 293 | "GetTasksRecursive", /* method */ |
173 | @@ -287,7 +305,7 @@ | |||
174 | 287 | return {}; | 305 | return {}; |
175 | 288 | } | 306 | } |
176 | 289 | 307 | ||
178 | 290 | GVariant* vpids = g_variant_get_child_value(vtpids, 0); | 308 | auto vpids = g_variant_get_child_value(vtpids, 0); |
179 | 291 | GVariantIter iter; | 309 | GVariantIter iter; |
180 | 292 | g_variant_iter_init(&iter, vpids); | 310 | g_variant_iter_init(&iter, vpids); |
181 | 293 | gint32 pid; | 311 | gint32 pid; |
182 | @@ -394,7 +412,7 @@ | |||
183 | 394 | return {}; | 412 | return {}; |
184 | 395 | } | 413 | } |
185 | 396 | 414 | ||
187 | 397 | GVariant* instance_list = g_variant_get_child_value(instance_tuple, 0); | 415 | auto instance_list = g_variant_get_child_value(instance_tuple, 0); |
188 | 398 | g_variant_unref(instance_tuple); | 416 | g_variant_unref(instance_tuple); |
189 | 399 | 417 | ||
190 | 400 | GVariantIter instance_iter; | 418 | GVariantIter instance_iter; |
191 | @@ -425,12 +443,12 @@ | |||
192 | 425 | continue; | 443 | continue; |
193 | 426 | } | 444 | } |
194 | 427 | 445 | ||
196 | 428 | GVariant* props_dict = g_variant_get_child_value(props_tuple, 0); | 446 | auto props_dict = g_variant_get_child_value(props_tuple, 0); |
197 | 429 | 447 | ||
199 | 430 | GVariant* namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING); | 448 | auto namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING); |
200 | 431 | if (namev != nullptr) | 449 | if (namev != nullptr) |
201 | 432 | { | 450 | { |
203 | 433 | auto name = g_variant_get_string(namev, NULL); | 451 | auto name = g_variant_get_string(namev, nullptr); |
204 | 434 | g_debug("Adding instance for job '%s': %s", job.c_str(), name); | 452 | g_debug("Adding instance for job '%s': %s", job.c_str(), name); |
205 | 435 | instances.push_back(name); | 453 | instances.push_back(name); |
206 | 436 | g_variant_unref(namev); | 454 | g_variant_unref(namev); |
207 | @@ -487,7 +505,7 @@ | |||
208 | 487 | zeitgeist_log_insert_event(zgLog_.get(), /* log */ | 505 | zeitgeist_log_insert_event(zgLog_.get(), /* log */ |
209 | 488 | event, /* event */ | 506 | event, /* event */ |
210 | 489 | nullptr, /* cancellable */ | 507 | nullptr, /* cancellable */ |
212 | 490 | [](GObject* obj, GAsyncResult* res, gpointer user_data) -> void { | 508 | [](GObject* obj, GAsyncResult* res, gpointer user_data) { |
213 | 491 | GError* error = nullptr; | 509 | GError* error = nullptr; |
214 | 492 | GArray* result = nullptr; | 510 | GArray* result = nullptr; |
215 | 493 | 511 | ||
216 | @@ -517,24 +535,207 @@ | |||
217 | 517 | return _iconFinders[basePath]; | 535 | return _iconFinders[basePath]; |
218 | 518 | } | 536 | } |
219 | 519 | 537 | ||
238 | 520 | #if 0 | 538 | /** Structure to track the data needed for upstart events. This cleans |
239 | 521 | void | 539 | up the lifecycle as we're passing this as a pointer through the |
240 | 522 | Registry::Impl::setManager (Registry::Manager* manager) | 540 | GLib calls. */ |
241 | 523 | { | 541 | struct upstartEventData |
242 | 524 | if (_manager != nullptr) | 542 | { |
243 | 525 | { | 543 | /** Keeping a weak pointer because the handle is held by |
244 | 526 | throw std::runtime_error("Already have a manager and trying to set another"); | 544 | the registry implementation. */ |
245 | 527 | } | 545 | std::weak_ptr<Registry> weakReg; |
246 | 528 | 546 | }; | |
247 | 529 | _manager = manager; | 547 | |
248 | 530 | } | 548 | /** Take the GVariant of parameters and turn them into an application and |
249 | 531 | 549 | and instance. Easier to read in the smaller function */ | |
250 | 532 | void | 550 | std::tuple<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> Registry::Impl::managerParams( |
251 | 533 | Registry::Impl::clearManager () | 551 | const std::shared_ptr<GVariant>& params, const std::shared_ptr<Registry>& reg) |
252 | 534 | { | 552 | { |
253 | 535 | _manager = nullptr; | 553 | std::shared_ptr<Application> app; |
254 | 536 | } | 554 | std::shared_ptr<Application::Instance> instance; |
255 | 537 | #endif | 555 | |
256 | 556 | const gchar* cappid = nullptr; | ||
257 | 557 | g_variant_get(params.get(), "(&s)", &cappid); | ||
258 | 558 | |||
259 | 559 | if (cappid != nullptr) | ||
260 | 560 | { | ||
261 | 561 | auto appid = ubuntu::app_launch::AppID::find(reg, cappid); | ||
262 | 562 | app = ubuntu::app_launch::Application::create(appid, reg); | ||
263 | 563 | } | ||
264 | 564 | |||
265 | 565 | return std::make_tuple(app, instance); | ||
266 | 566 | } | ||
267 | 567 | |||
268 | 568 | /** Used to store data for manager based signal handlers. Has a link to the | ||
269 | 569 | registry and the callback to use in a C++ style. */ | ||
270 | 570 | struct managerEventData | ||
271 | 571 | { | ||
272 | 572 | /* Keeping a weak pointer because the handle is held by | ||
273 | 573 | the registry implementation. */ | ||
274 | 574 | std::weak_ptr<Registry> weakReg; | ||
275 | 575 | std::function<void(const std::shared_ptr<Registry>& reg, | ||
276 | 576 | const std::shared_ptr<Application>& app, | ||
277 | 577 | const std::shared_ptr<Application::Instance>& instance, | ||
278 | 578 | const std::shared_ptr<GDBusConnection>& dbus, | ||
279 | 579 | const std::string& sender, | ||
280 | 580 | const std::shared_ptr<GVariant>& params)> | ||
281 | 581 | func; | ||
282 | 582 | }; | ||
283 | 583 | |||
284 | 584 | /** Register for a signal for the manager. All of the signals needed this same | ||
285 | 585 | code so it got pulled out into a function. Takes the same of the signal, the registry | ||
286 | 586 | that we're using and a function to call after we've messaged all the parameters | ||
287 | 587 | into being something C++-ish. */ | ||
288 | 588 | guint Registry::Impl::managerSignalHelper(const std::shared_ptr<Registry>& reg, | ||
289 | 589 | const std::string& signalname, | ||
290 | 590 | std::function<void(const std::shared_ptr<Registry>& reg, | ||
291 | 591 | const std::shared_ptr<Application>& app, | ||
292 | 592 | const std::shared_ptr<Application::Instance>& instance, | ||
293 | 593 | const std::shared_ptr<GDBusConnection>& dbus, | ||
294 | 594 | const std::string& sender, | ||
295 | 595 | const std::shared_ptr<GVariant>& params)> responsefunc) | ||
296 | 596 | { | ||
297 | 597 | auto focusdata = new managerEventData{reg, responsefunc}; | ||
298 | 598 | |||
299 | 599 | return g_dbus_connection_signal_subscribe( | ||
300 | 600 | reg->impl->_dbus.get(), /* bus */ | ||
301 | 601 | nullptr, /* sender */ | ||
302 | 602 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
303 | 603 | signalname.c_str(), /* signal */ | ||
304 | 604 | "/", /* path */ | ||
305 | 605 | nullptr, /* arg0 */ | ||
306 | 606 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
307 | 607 | [](GDBusConnection* cconn, const gchar* csender, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
308 | 608 | gpointer user_data) { | ||
309 | 609 | auto data = static_cast<managerEventData*>(user_data); | ||
310 | 610 | auto reg = data->weakReg.lock(); | ||
311 | 611 | |||
312 | 612 | if (!reg) | ||
313 | 613 | { | ||
314 | 614 | g_warning("Registry object invalid!"); | ||
315 | 615 | return; | ||
316 | 616 | } | ||
317 | 617 | |||
318 | 618 | /* If we're still connected and the manager has been cleared | ||
319 | 619 | we'll just be a no-op */ | ||
320 | 620 | if (!reg->impl->manager_) | ||
321 | 621 | { | ||
322 | 622 | return; | ||
323 | 623 | } | ||
324 | 624 | |||
325 | 625 | auto vparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); | ||
326 | 626 | auto conn = std::shared_ptr<GDBusConnection>(reinterpret_cast<GDBusConnection*>(g_object_ref(cconn)), | ||
327 | 627 | [](GDBusConnection* con) { g_clear_object(&con); }); | ||
328 | 628 | std::string sender = csender; | ||
329 | 629 | std::shared_ptr<Application> app; | ||
330 | 630 | std::shared_ptr<Application::Instance> instance; | ||
331 | 631 | |||
332 | 632 | std::tie(app, instance) = managerParams(vparams, reg); | ||
333 | 633 | |||
334 | 634 | data->func(reg, app, instance, conn, sender, vparams); | ||
335 | 635 | }, | ||
336 | 636 | focusdata, | ||
337 | 637 | [](gpointer user_data) { | ||
338 | 638 | auto data = static_cast<managerEventData*>(user_data); | ||
339 | 639 | delete data; | ||
340 | 640 | }); /* user data destroy */ | ||
341 | 641 | } | ||
342 | 642 | |||
343 | 643 | /** Set the manager for the registry. This includes tracking the pointer | ||
344 | 644 | as well as setting up the signals to call back into the manager. The | ||
345 | 645 | signals are only setup once per registry even if the manager is cleared | ||
346 | 646 | and changed again. They will just be no-op's in those cases. | ||
347 | 647 | */ | ||
348 | 648 | void Registry::Impl::setManager(const std::shared_ptr<Registry::Manager>& manager, const std::shared_ptr<Registry>& reg) | ||
349 | 649 | { | ||
350 | 650 | if (!reg) | ||
351 | 651 | { | ||
352 | 652 | throw std::invalid_argument("Passed null registry to setManager()"); | ||
353 | 653 | } | ||
354 | 654 | |||
355 | 655 | if (reg->impl->manager_) | ||
356 | 656 | { | ||
357 | 657 | throw std::logic_error("Already have a manager and trying to set another"); | ||
358 | 658 | } | ||
359 | 659 | |||
360 | 660 | g_debug("Setting a new manager"); | ||
361 | 661 | reg->impl->manager_ = manager; | ||
362 | 662 | |||
363 | 663 | std::call_once(reg->impl->flag_managerSignals, [reg]() { | ||
364 | 664 | if (!reg->impl->thread.executeOnThread<bool>([reg]() { | ||
365 | 665 | reg->impl->handle_managerSignalFocus = managerSignalHelper( | ||
366 | 666 | reg, "UnityFocusRequest", | ||
367 | 667 | [](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app, | ||
368 | 668 | const std::shared_ptr<Application::Instance>& instance, | ||
369 | 669 | const std::shared_ptr<GDBusConnection>& /* conn */, const std::string& /* sender */, | ||
370 | 670 | const std::shared_ptr<GVariant>& /* params */) { | ||
371 | 671 | /* Nothing to do today */ | ||
372 | 672 | reg->impl->manager_->focusRequest(app, instance, [](bool response) { | ||
373 | 673 | /* NOTE: We have no clue what thread this is gonna be | ||
374 | 674 | executed on, but since we're just talking to the GDBus | ||
375 | 675 | thread it isn't an issue today. Be careful in changing | ||
376 | 676 | this code. */ | ||
377 | 677 | }); | ||
378 | 678 | }); | ||
379 | 679 | reg->impl->handle_managerSignalStarting = managerSignalHelper( | ||
380 | 680 | reg, "UnityStartingBroadcast", | ||
381 | 681 | [](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app, | ||
382 | 682 | const std::shared_ptr<Application::Instance>& instance, | ||
383 | 683 | const std::shared_ptr<GDBusConnection>& conn, const std::string& sender, | ||
384 | 684 | const std::shared_ptr<GVariant>& params) { | ||
385 | 685 | |||
386 | 686 | reg->impl->manager_->startingRequest(app, instance, [conn, sender, params](bool response) { | ||
387 | 687 | /* NOTE: We have no clue what thread this is gonna be | ||
388 | 688 | executed on, but since we're just talking to the GDBus | ||
389 | 689 | thread it isn't an issue today. Be careful in changing | ||
390 | 690 | this code. */ | ||
391 | 691 | if (response) | ||
392 | 692 | { | ||
393 | 693 | g_dbus_connection_emit_signal(conn.get(), sender.c_str(), /* destination */ | ||
394 | 694 | "/", /* path */ | ||
395 | 695 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
396 | 696 | "UnityStartingSignal", /* signal */ | ||
397 | 697 | params.get(), /* params, the same */ | ||
398 | 698 | nullptr); /* error */ | ||
399 | 699 | } | ||
400 | 700 | }); | ||
401 | 701 | }); | ||
402 | 702 | reg->impl->handle_managerSignalResume = managerSignalHelper( | ||
403 | 703 | reg, "UnityResumeRequest", | ||
404 | 704 | [](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app, | ||
405 | 705 | const std::shared_ptr<Application::Instance>& instance, | ||
406 | 706 | const std::shared_ptr<GDBusConnection>& conn, const std::string& sender, | ||
407 | 707 | const std::shared_ptr<GVariant>& params) { | ||
408 | 708 | reg->impl->manager_->resumeRequest(app, instance, [conn, sender, params](bool response) { | ||
409 | 709 | /* NOTE: We have no clue what thread this is gonna be | ||
410 | 710 | executed on, but since we're just talking to the GDBus | ||
411 | 711 | thread it isn't an issue today. Be careful in changing | ||
412 | 712 | this code. */ | ||
413 | 713 | if (response) | ||
414 | 714 | { | ||
415 | 715 | g_dbus_connection_emit_signal(conn.get(), sender.c_str(), /* destination */ | ||
416 | 716 | "/", /* path */ | ||
417 | 717 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
418 | 718 | "UnityResumeResponse", /* signal */ | ||
419 | 719 | params.get(), /* params, the same */ | ||
420 | 720 | nullptr); /* error */ | ||
421 | 721 | } | ||
422 | 722 | }); | ||
423 | 723 | }); | ||
424 | 724 | |||
425 | 725 | return true; | ||
426 | 726 | })) | ||
427 | 727 | { | ||
428 | 728 | g_warning("Unable to install manager signals"); | ||
429 | 729 | } | ||
430 | 730 | }); | ||
431 | 731 | } | ||
432 | 732 | |||
433 | 733 | /** Clear the manager pointer */ | ||
434 | 734 | void Registry::Impl::clearManager() | ||
435 | 735 | { | ||
436 | 736 | g_debug("Clearing the manager"); | ||
437 | 737 | manager_.reset(); | ||
438 | 738 | } | ||
439 | 538 | 739 | ||
440 | 539 | /** App start watching, if we're registered for the signal we | 740 | /** App start watching, if we're registered for the signal we |
441 | 540 | can't wait on it. We are making this static right now because | 741 | can't wait on it. We are making this static right now because |
442 | @@ -557,5 +758,340 @@ | |||
443 | 557 | return watchingAppStarting_; | 758 | return watchingAppStarting_; |
444 | 558 | } | 759 | } |
445 | 559 | 760 | ||
446 | 761 | /** Regex to parse the JOB environment variable from Upstart */ | ||
447 | 762 | const std::regex jobenv_regex{"^JOB=(application\\-(?:click|snap|legacy))$"}; | ||
448 | 763 | /** Regex to parse the INSTANCE environment variable from Upstart */ | ||
449 | 764 | const std::regex instanceenv_regex{"^INSTANCE=(.*?)(?:\\-([0-9]*))?+$"}; | ||
450 | 765 | |||
451 | 766 | /** Core of most of the events that come from Upstart directly. Includes parsing of the | ||
452 | 767 | Upstart event environment and calling the appropriate signal with the right Application | ||
453 | 768 | object and eventually its instance */ | ||
454 | 769 | void Registry::Impl::upstartEventEmitted( | ||
455 | 770 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& signal, | ||
456 | 771 | const std::shared_ptr<GVariant>& params, | ||
457 | 772 | const std::shared_ptr<Registry>& reg) | ||
458 | 773 | { | ||
459 | 774 | std::string jobname; | ||
460 | 775 | std::string sappid; | ||
461 | 776 | std::string instance; | ||
462 | 777 | |||
463 | 778 | gchar* env = nullptr; | ||
464 | 779 | auto envs = g_variant_get_child_value(params.get(), 1); | ||
465 | 780 | GVariantIter iter; | ||
466 | 781 | g_variant_iter_init(&iter, envs); | ||
467 | 782 | |||
468 | 783 | while (g_variant_iter_loop(&iter, "s", &env)) | ||
469 | 784 | { | ||
470 | 785 | std::smatch match; | ||
471 | 786 | std::string senv = env; | ||
472 | 787 | |||
473 | 788 | if (std::regex_match(senv, match, jobenv_regex)) | ||
474 | 789 | { | ||
475 | 790 | jobname = match[1].str(); | ||
476 | 791 | } | ||
477 | 792 | else if (std::regex_match(senv, match, instanceenv_regex)) | ||
478 | 793 | { | ||
479 | 794 | sappid = match[1].str(); | ||
480 | 795 | instance = match[2].str(); | ||
481 | 796 | } | ||
482 | 797 | } | ||
483 | 798 | |||
484 | 799 | g_variant_unref(envs); | ||
485 | 800 | |||
486 | 801 | if (jobname.empty()) | ||
487 | 802 | { | ||
488 | 803 | return; | ||
489 | 804 | } | ||
490 | 805 | |||
491 | 806 | g_debug("Upstart Event for job '%s' appid '%s' instance '%s'", jobname.c_str(), sappid.c_str(), instance.c_str()); | ||
492 | 807 | |||
493 | 808 | auto appid = AppID::find(reg, sappid); | ||
494 | 809 | auto app = Application::create(appid, reg); | ||
495 | 810 | |||
496 | 811 | // TODO: Figure out creating instances | ||
497 | 812 | |||
498 | 813 | signal(app, {}); | ||
499 | 814 | } | ||
500 | 815 | |||
501 | 816 | /** Grab the signal object for application startup. If we're not already listing for | ||
502 | 817 | those signals this sets up a listener for them. */ | ||
503 | 818 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& | ||
504 | 819 | Registry::Impl::appStarted(const std::shared_ptr<Registry>& reg) | ||
505 | 820 | { | ||
506 | 821 | std::call_once(flag_appStarted, [reg]() { | ||
507 | 822 | reg->impl->thread.executeOnThread<bool>([reg]() { | ||
508 | 823 | auto data = new upstartEventData{reg}; | ||
509 | 824 | |||
510 | 825 | reg->impl->handle_appStarted = g_dbus_connection_signal_subscribe( | ||
511 | 826 | reg->impl->_dbus.get(), /* bus */ | ||
512 | 827 | nullptr, /* sender */ | ||
513 | 828 | DBUS_INTERFACE_UPSTART, /* interface */ | ||
514 | 829 | "EventEmitted", /* signal */ | ||
515 | 830 | DBUS_PATH_UPSTART, /* path */ | ||
516 | 831 | "started", /* arg0 */ | ||
517 | 832 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
518 | 833 | [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
519 | 834 | gpointer user_data) { | ||
520 | 835 | auto data = static_cast<upstartEventData*>(user_data); | ||
521 | 836 | auto reg = data->weakReg.lock(); | ||
522 | 837 | |||
523 | 838 | if (!reg) | ||
524 | 839 | { | ||
525 | 840 | g_warning("Registry object invalid!"); | ||
526 | 841 | return; | ||
527 | 842 | } | ||
528 | 843 | |||
529 | 844 | auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); | ||
530 | 845 | reg->impl->upstartEventEmitted(reg->impl->sig_appStarted, sparams, reg); | ||
531 | 846 | }, /* callback */ | ||
532 | 847 | data, /* user data */ | ||
533 | 848 | [](gpointer user_data) { | ||
534 | 849 | auto data = static_cast<upstartEventData*>(user_data); | ||
535 | 850 | delete data; | ||
536 | 851 | }); /* user data destroy */ | ||
537 | 852 | |||
538 | 853 | return true; | ||
539 | 854 | }); | ||
540 | 855 | }); | ||
541 | 856 | |||
542 | 857 | return sig_appStarted; | ||
543 | 858 | } | ||
544 | 859 | |||
545 | 860 | /** Grab the signal object for application stopping. If we're not already listing for | ||
546 | 861 | those signals this sets up a listener for them. */ | ||
547 | 862 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& | ||
548 | 863 | Registry::Impl::appStopped(const std::shared_ptr<Registry>& reg) | ||
549 | 864 | { | ||
550 | 865 | std::call_once(flag_appStopped, [reg]() { | ||
551 | 866 | reg->impl->thread.executeOnThread<bool>([reg]() { | ||
552 | 867 | auto data = new upstartEventData{reg}; | ||
553 | 868 | |||
554 | 869 | reg->impl->handle_appStopped = g_dbus_connection_signal_subscribe( | ||
555 | 870 | reg->impl->_dbus.get(), /* bus */ | ||
556 | 871 | nullptr, /* sender */ | ||
557 | 872 | DBUS_INTERFACE_UPSTART, /* interface */ | ||
558 | 873 | "EventEmitted", /* signal */ | ||
559 | 874 | DBUS_PATH_UPSTART, /* path */ | ||
560 | 875 | "stopped", /* arg0 */ | ||
561 | 876 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
562 | 877 | [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
563 | 878 | gpointer user_data) { | ||
564 | 879 | auto data = static_cast<upstartEventData*>(user_data); | ||
565 | 880 | auto reg = data->weakReg.lock(); | ||
566 | 881 | |||
567 | 882 | if (!reg) | ||
568 | 883 | { | ||
569 | 884 | g_warning("Registry object invalid!"); | ||
570 | 885 | return; | ||
571 | 886 | } | ||
572 | 887 | |||
573 | 888 | auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); | ||
574 | 889 | reg->impl->upstartEventEmitted(reg->impl->sig_appStopped, sparams, reg); | ||
575 | 890 | }, /* callback */ | ||
576 | 891 | data, /* user data */ | ||
577 | 892 | [](gpointer user_data) { | ||
578 | 893 | auto data = static_cast<upstartEventData*>(user_data); | ||
579 | 894 | delete data; | ||
580 | 895 | }); /* user data destroy */ | ||
581 | 896 | |||
582 | 897 | return true; | ||
583 | 898 | }); | ||
584 | 899 | }); | ||
585 | 900 | |||
586 | 901 | return sig_appStopped; | ||
587 | 902 | } | ||
588 | 903 | |||
589 | 904 | /** Grab the signal object for application failing. If we're not already listing for | ||
590 | 905 | those signals this sets up a listener for them. */ | ||
591 | 906 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, Registry::FailureType>& | ||
592 | 907 | Registry::Impl::appFailed(const std::shared_ptr<Registry>& reg) | ||
593 | 908 | { | ||
594 | 909 | std::call_once(flag_appFailed, [reg]() { | ||
595 | 910 | reg->impl->thread.executeOnThread<bool>([reg]() { | ||
596 | 911 | auto data = new upstartEventData{reg}; | ||
597 | 912 | |||
598 | 913 | reg->impl->handle_appFailed = g_dbus_connection_signal_subscribe( | ||
599 | 914 | reg->impl->_dbus.get(), /* bus */ | ||
600 | 915 | nullptr, /* sender */ | ||
601 | 916 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
602 | 917 | "ApplicationFailed", /* signal */ | ||
603 | 918 | "/", /* path */ | ||
604 | 919 | nullptr, /* arg0 */ | ||
605 | 920 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
606 | 921 | [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
607 | 922 | gpointer user_data) { | ||
608 | 923 | auto data = static_cast<upstartEventData*>(user_data); | ||
609 | 924 | auto reg = data->weakReg.lock(); | ||
610 | 925 | |||
611 | 926 | if (!reg) | ||
612 | 927 | { | ||
613 | 928 | g_warning("Registry object invalid!"); | ||
614 | 929 | return; | ||
615 | 930 | } | ||
616 | 931 | |||
617 | 932 | const gchar* sappid = nullptr; | ||
618 | 933 | const gchar* typestr = nullptr; | ||
619 | 934 | |||
620 | 935 | Registry::FailureType type = Registry::FailureType::CRASH; | ||
621 | 936 | g_variant_get(params, "(&s&s)", &sappid, &typestr); | ||
622 | 937 | |||
623 | 938 | if (g_strcmp0("crash", typestr) == 0) | ||
624 | 939 | { | ||
625 | 940 | type = Registry::FailureType::CRASH; | ||
626 | 941 | } | ||
627 | 942 | else if (g_strcmp0("start-failure", typestr) == 0) | ||
628 | 943 | { | ||
629 | 944 | type = Registry::FailureType::START_FAILURE; | ||
630 | 945 | } | ||
631 | 946 | else | ||
632 | 947 | { | ||
633 | 948 | g_warning("Application failure type '%s' unknown, reporting as a crash", typestr); | ||
634 | 949 | } | ||
635 | 950 | |||
636 | 951 | auto appid = AppID::find(reg, sappid); | ||
637 | 952 | auto app = Application::create(appid, reg); | ||
638 | 953 | |||
639 | 954 | /* TODO: Instance issues */ | ||
640 | 955 | |||
641 | 956 | reg->impl->sig_appFailed(app, {}, type); | ||
642 | 957 | }, /* callback */ | ||
643 | 958 | data, /* user data */ | ||
644 | 959 | [](gpointer user_data) { | ||
645 | 960 | auto data = static_cast<upstartEventData*>(user_data); | ||
646 | 961 | delete data; | ||
647 | 962 | }); /* user data destroy */ | ||
648 | 963 | |||
649 | 964 | return true; | ||
650 | 965 | }); | ||
651 | 966 | }); | ||
652 | 967 | |||
653 | 968 | return sig_appFailed; | ||
654 | 969 | } | ||
655 | 970 | |||
656 | 971 | /** Core handler for pause and resume events. Includes turning the GVariant | ||
657 | 972 | pid list into a std::vector and getting the application object. */ | ||
658 | 973 | void Registry::Impl::pauseEventEmitted(core::Signal<const std::shared_ptr<Application>&, | ||
659 | 974 | const std::shared_ptr<Application::Instance>&, | ||
660 | 975 | const std::vector<pid_t>&>& signal, | ||
661 | 976 | const std::shared_ptr<GVariant>& params, | ||
662 | 977 | const std::shared_ptr<Registry>& reg) | ||
663 | 978 | { | ||
664 | 979 | std::vector<pid_t> pids; | ||
665 | 980 | auto vappid = g_variant_get_child_value(params.get(), 0); | ||
666 | 981 | auto vpids = g_variant_get_child_value(params.get(), 1); | ||
667 | 982 | guint64 pid; | ||
668 | 983 | GVariantIter thispid; | ||
669 | 984 | g_variant_iter_init(&thispid, vpids); | ||
670 | 985 | |||
671 | 986 | while (g_variant_iter_loop(&thispid, "t", &pid)) | ||
672 | 987 | { | ||
673 | 988 | pids.emplace_back(pid); | ||
674 | 989 | } | ||
675 | 990 | |||
676 | 991 | auto cappid = g_variant_get_string(vappid, nullptr); | ||
677 | 992 | auto appid = ubuntu::app_launch::AppID::find(reg, cappid); | ||
678 | 993 | auto app = Application::create(appid, reg); | ||
679 | 994 | |||
680 | 995 | /* TODO: Instance */ | ||
681 | 996 | signal(app, {}, pids); | ||
682 | 997 | |||
683 | 998 | g_variant_unref(vappid); | ||
684 | 999 | g_variant_unref(vpids); | ||
685 | 1000 | |||
686 | 1001 | return; | ||
687 | 1002 | } | ||
688 | 1003 | |||
689 | 1004 | /** Grab the signal object for application paused. If we're not already listing for | ||
690 | 1005 | those signals this sets up a listener for them. */ | ||
691 | 1006 | core::Signal<const std::shared_ptr<Application>&, | ||
692 | 1007 | const std::shared_ptr<Application::Instance>&, | ||
693 | 1008 | const std::vector<pid_t>&>& | ||
694 | 1009 | Registry::Impl::appPaused(const std::shared_ptr<Registry>& reg) | ||
695 | 1010 | { | ||
696 | 1011 | std::call_once(flag_appPaused, [&]() { | ||
697 | 1012 | reg->impl->thread.executeOnThread<bool>([reg]() { | ||
698 | 1013 | auto data = new upstartEventData{reg}; | ||
699 | 1014 | |||
700 | 1015 | reg->impl->handle_appPaused = g_dbus_connection_signal_subscribe( | ||
701 | 1016 | reg->impl->_dbus.get(), /* bus */ | ||
702 | 1017 | nullptr, /* sender */ | ||
703 | 1018 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
704 | 1019 | "ApplicationPaused", /* signal */ | ||
705 | 1020 | "/", /* path */ | ||
706 | 1021 | nullptr, /* arg0 */ | ||
707 | 1022 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
708 | 1023 | [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
709 | 1024 | gpointer user_data) { | ||
710 | 1025 | auto data = static_cast<upstartEventData*>(user_data); | ||
711 | 1026 | auto reg = data->weakReg.lock(); | ||
712 | 1027 | |||
713 | 1028 | if (!reg) | ||
714 | 1029 | { | ||
715 | 1030 | g_warning("Registry object invalid!"); | ||
716 | 1031 | return; | ||
717 | 1032 | } | ||
718 | 1033 | |||
719 | 1034 | auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); | ||
720 | 1035 | reg->impl->pauseEventEmitted(reg->impl->sig_appPaused, sparams, reg); | ||
721 | 1036 | }, /* callback */ | ||
722 | 1037 | data, /* user data */ | ||
723 | 1038 | [](gpointer user_data) { | ||
724 | 1039 | auto data = static_cast<upstartEventData*>(user_data); | ||
725 | 1040 | delete data; | ||
726 | 1041 | }); /* user data destroy */ | ||
727 | 1042 | |||
728 | 1043 | return true; | ||
729 | 1044 | }); | ||
730 | 1045 | }); | ||
731 | 1046 | |||
732 | 1047 | return sig_appPaused; | ||
733 | 1048 | } | ||
734 | 1049 | |||
735 | 1050 | /** Grab the signal object for application resumed. If we're not already listing for | ||
736 | 1051 | those signals this sets up a listener for them. */ | ||
737 | 1052 | core::Signal<const std::shared_ptr<Application>&, | ||
738 | 1053 | const std::shared_ptr<Application::Instance>&, | ||
739 | 1054 | const std::vector<pid_t>&>& | ||
740 | 1055 | Registry::Impl::appResumed(const std::shared_ptr<Registry>& reg) | ||
741 | 1056 | { | ||
742 | 1057 | std::call_once(flag_appResumed, [&]() { | ||
743 | 1058 | reg->impl->thread.executeOnThread<bool>([reg]() { | ||
744 | 1059 | auto data = new upstartEventData{reg}; | ||
745 | 1060 | |||
746 | 1061 | reg->impl->handle_appResumed = g_dbus_connection_signal_subscribe( | ||
747 | 1062 | reg->impl->_dbus.get(), /* bus */ | ||
748 | 1063 | nullptr, /* sender */ | ||
749 | 1064 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
750 | 1065 | "ApplicationResumed", /* signal */ | ||
751 | 1066 | "/", /* path */ | ||
752 | 1067 | nullptr, /* arg0 */ | ||
753 | 1068 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
754 | 1069 | [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
755 | 1070 | gpointer user_data) { | ||
756 | 1071 | auto data = static_cast<upstartEventData*>(user_data); | ||
757 | 1072 | auto reg = data->weakReg.lock(); | ||
758 | 1073 | |||
759 | 1074 | if (!reg) | ||
760 | 1075 | { | ||
761 | 1076 | g_warning("Registry object invalid!"); | ||
762 | 1077 | return; | ||
763 | 1078 | } | ||
764 | 1079 | |||
765 | 1080 | auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); | ||
766 | 1081 | reg->impl->pauseEventEmitted(reg->impl->sig_appResumed, sparams, reg); | ||
767 | 1082 | }, /* callback */ | ||
768 | 1083 | data, /* user data */ | ||
769 | 1084 | [](gpointer user_data) { | ||
770 | 1085 | auto data = static_cast<upstartEventData*>(user_data); | ||
771 | 1086 | delete data; | ||
772 | 1087 | }); /* user data destroy */ | ||
773 | 1088 | |||
774 | 1089 | return true; | ||
775 | 1090 | }); | ||
776 | 1091 | }); | ||
777 | 1092 | |||
778 | 1093 | return sig_appResumed; | ||
779 | 1094 | } | ||
780 | 1095 | |||
781 | 560 | } // namespace app_launch | 1096 | } // namespace app_launch |
782 | 561 | } // namespace ubuntu | 1097 | } // namespace ubuntu |
783 | 562 | 1098 | ||
784 | === modified file 'libubuntu-app-launch/registry-impl.h' | |||
785 | --- libubuntu-app-launch/registry-impl.h 2016-09-23 22:30:51 +0000 | |||
786 | +++ libubuntu-app-launch/registry-impl.h 2017-01-24 04:21:42 +0000 | |||
787 | @@ -53,10 +53,9 @@ | |||
788 | 53 | std::list<AppID::Package> getClickPackages(); | 53 | std::list<AppID::Package> getClickPackages(); |
789 | 54 | std::string getClickDir(const std::string& package); | 54 | std::string getClickDir(const std::string& package); |
790 | 55 | 55 | ||
795 | 56 | #if 0 | 56 | static void setManager(const std::shared_ptr<Registry::Manager>& manager, |
796 | 57 | void setManager (Registry::Manager* manager); | 57 | const std::shared_ptr<Registry>& registry); |
797 | 58 | void clearManager (); | 58 | void clearManager(); |
794 | 59 | #endif | ||
798 | 60 | 59 | ||
799 | 61 | /** Shared context thread for events and background tasks | 60 | /** Shared context thread for events and background tasks |
800 | 62 | that UAL subtasks are doing */ | 61 | that UAL subtasks are doing */ |
801 | @@ -82,6 +81,22 @@ | |||
802 | 82 | static std::string printJson(std::shared_ptr<JsonObject> jsonobj); | 81 | static std::string printJson(std::shared_ptr<JsonObject> jsonobj); |
803 | 83 | static std::string printJson(std::shared_ptr<JsonNode> jsonnode); | 82 | static std::string printJson(std::shared_ptr<JsonNode> jsonnode); |
804 | 84 | 83 | ||
805 | 84 | /* Signals to discover what is happening to apps */ | ||
806 | 85 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& appStarted( | ||
807 | 86 | const std::shared_ptr<Registry>& reg); | ||
808 | 87 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& appStopped( | ||
809 | 88 | const std::shared_ptr<Registry>& reg); | ||
810 | 89 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, FailureType>& | ||
811 | 90 | appFailed(const std::shared_ptr<Registry>& reg); | ||
812 | 91 | core::Signal<const std::shared_ptr<Application>&, | ||
813 | 92 | const std::shared_ptr<Application::Instance>&, | ||
814 | 93 | const std::vector<pid_t>&>& | ||
815 | 94 | appPaused(const std::shared_ptr<Registry>& reg); | ||
816 | 95 | core::Signal<const std::shared_ptr<Application>&, | ||
817 | 96 | const std::shared_ptr<Application::Instance>&, | ||
818 | 97 | const std::vector<pid_t>&>& | ||
819 | 98 | appResumed(const std::shared_ptr<Registry>& reg); | ||
820 | 99 | |||
821 | 85 | /* Signal Hints */ | 100 | /* Signal Hints */ |
822 | 86 | /* NOTE: Static because we don't have registry instances in the C | 101 | /* NOTE: Static because we don't have registry instances in the C |
823 | 87 | code right now. We want these to not be static in the future */ | 102 | code right now. We want these to not be static in the future */ |
824 | @@ -89,22 +104,84 @@ | |||
825 | 89 | static bool isWatchingAppStarting(); | 104 | static bool isWatchingAppStarting(); |
826 | 90 | 105 | ||
827 | 91 | private: | 106 | private: |
835 | 92 | Registry* _registry; | 107 | Registry* _registry; /**< The Registry that we're spawned from */ |
836 | 93 | #if 0 | 108 | std::shared_ptr<Registry::Manager> manager_; /**< Application manager if registered */ |
837 | 94 | Registry::Manager* _manager; | 109 | |
838 | 95 | #endif | 110 | std::shared_ptr<ClickDB> _clickDB; /**< Shared instance of the Click Database */ |
839 | 96 | 111 | std::shared_ptr<ClickUser> _clickUser; /**< Click database filtered by the current user */ | |
840 | 97 | std::shared_ptr<ClickDB> _clickDB; | 112 | |
841 | 98 | std::shared_ptr<ClickUser> _clickUser; | 113 | /** Signal object for applications started */ |
842 | 114 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&> sig_appStarted; | ||
843 | 115 | /** Signal object for applications stopped */ | ||
844 | 116 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&> sig_appStopped; | ||
845 | 117 | /** Signal object for applications failed */ | ||
846 | 118 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, FailureType> | ||
847 | 119 | sig_appFailed; | ||
848 | 120 | /** Signal object for applications paused */ | ||
849 | 121 | core::Signal<const std::shared_ptr<Application>&, | ||
850 | 122 | const std::shared_ptr<Application::Instance>&, | ||
851 | 123 | const std::vector<pid_t>&> | ||
852 | 124 | sig_appPaused; | ||
853 | 125 | /** Signal object for applications resumed */ | ||
854 | 126 | core::Signal<const std::shared_ptr<Application>&, | ||
855 | 127 | const std::shared_ptr<Application::Instance>&, | ||
856 | 128 | const std::vector<pid_t>&> | ||
857 | 129 | sig_appResumed; | ||
858 | 130 | |||
859 | 131 | guint handle_appStarted{0}; /**< GDBus signal watcher handle for app started signal */ | ||
860 | 132 | guint handle_appStopped{0}; /**< GDBus signal watcher handle for app stopped signal */ | ||
861 | 133 | guint handle_appFailed{0}; /**< GDBus signal watcher handle for app failed signal */ | ||
862 | 134 | guint handle_appPaused{0}; /**< GDBus signal watcher handle for app paused signal */ | ||
863 | 135 | guint handle_appResumed{0}; /**< GDBus signal watcher handle for app resumed signal */ | ||
864 | 136 | guint handle_managerSignalFocus{0}; /**< GDBus signal watcher handle for app focused signal */ | ||
865 | 137 | guint handle_managerSignalResume{0}; /**< GDBus signal watcher handle for app resumed signal */ | ||
866 | 138 | guint handle_managerSignalStarting{0}; /**< GDBus signal watcher handle for app starting signal */ | ||
867 | 139 | |||
868 | 140 | std::once_flag flag_appStarted; /**< Variable to track to see if signal handlers are installed for application | ||
869 | 141 | started */ | ||
870 | 142 | std::once_flag flag_appStopped; /**< Variable to track to see if signal handlers are installed for application | ||
871 | 143 | stopped */ | ||
872 | 144 | std::once_flag | ||
873 | 145 | flag_appFailed; /**< Variable to track to see if signal handlers are installed for application failed */ | ||
874 | 146 | std::once_flag | ||
875 | 147 | flag_appPaused; /**< Variable to track to see if signal handlers are installed for application paused */ | ||
876 | 148 | std::once_flag flag_appResumed; /**< Variable to track to see if signal handlers are installed for application | ||
877 | 149 | resumed */ | ||
878 | 150 | std::once_flag flag_managerSignals; /**< Variable to track to see if signal handlers are installed for the manager | ||
879 | 151 | signals of focused, resumed and starting */ | ||
880 | 152 | |||
881 | 153 | void upstartEventEmitted( | ||
882 | 154 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& signal, | ||
883 | 155 | const std::shared_ptr<GVariant>& params, | ||
884 | 156 | const std::shared_ptr<Registry>& reg); | ||
885 | 157 | void pauseEventEmitted(core::Signal<const std::shared_ptr<Application>&, | ||
886 | 158 | const std::shared_ptr<Application::Instance>&, | ||
887 | 159 | const std::vector<pid_t>&>& signal, | ||
888 | 160 | const std::shared_ptr<GVariant>& params, | ||
889 | 161 | const std::shared_ptr<Registry>& reg); | ||
890 | 162 | static std::tuple<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> managerParams( | ||
891 | 163 | const std::shared_ptr<GVariant>& params, const std::shared_ptr<Registry>& reg); | ||
892 | 164 | static guint managerSignalHelper(const std::shared_ptr<Registry>& reg, | ||
893 | 165 | const std::string& signalname, | ||
894 | 166 | std::function<void(const std::shared_ptr<Registry>& reg, | ||
895 | 167 | const std::shared_ptr<Application>& app, | ||
896 | 168 | const std::shared_ptr<Application::Instance>& instance, | ||
897 | 169 | const std::shared_ptr<GDBusConnection>&, | ||
898 | 170 | const std::string&, | ||
899 | 171 | const std::shared_ptr<GVariant>&)> responsefunc); | ||
900 | 99 | 172 | ||
901 | 100 | void initClick(); | 173 | void initClick(); |
902 | 101 | 174 | ||
903 | 175 | /** Shared instance of the Zeitgeist Log */ | ||
904 | 102 | std::shared_ptr<ZeitgeistLog> zgLog_; | 176 | std::shared_ptr<ZeitgeistLog> zgLog_; |
905 | 103 | 177 | ||
906 | 178 | /** Shared connection to CGManager */ | ||
907 | 104 | std::shared_ptr<GDBusConnection> cgManager_; | 179 | std::shared_ptr<GDBusConnection> cgManager_; |
908 | 105 | 180 | ||
909 | 106 | void initCGManager(); | 181 | void initCGManager(); |
910 | 107 | 182 | ||
911 | 183 | /** All of our icon finders based on the path that they're looking | ||
912 | 184 | into */ | ||
913 | 108 | std::unordered_map<std::string, std::shared_ptr<IconFinder>> _iconFinders; | 185 | std::unordered_map<std::string, std::shared_ptr<IconFinder>> _iconFinders; |
914 | 109 | 186 | ||
915 | 110 | /** Getting the Upstart job path is relatively expensive in | 187 | /** Getting the Upstart job path is relatively expensive in |
916 | 111 | 188 | ||
917 | === modified file 'libubuntu-app-launch/registry.cpp' | |||
918 | --- libubuntu-app-launch/registry.cpp 2016-08-26 17:33:34 +0000 | |||
919 | +++ libubuntu-app-launch/registry.cpp 2017-01-24 04:21:42 +0000 | |||
920 | @@ -57,7 +57,7 @@ | |||
921 | 57 | instances.splice(instances.begin(), connection->impl->upstartInstancesForJob("application-snap")); | 57 | instances.splice(instances.begin(), connection->impl->upstartInstancesForJob("application-snap")); |
922 | 58 | 58 | ||
923 | 59 | /* Remove the instance ID */ | 59 | /* Remove the instance ID */ |
925 | 60 | std::transform(instances.begin(), instances.end(), instances.begin(), [](std::string &instancename) -> std::string { | 60 | std::transform(instances.begin(), instances.end(), instances.begin(), [](std::string& instancename) -> std::string { |
926 | 61 | static const std::regex instanceregex("^(.*)-[0-9]*$"); | 61 | static const std::regex instanceregex("^(.*)-[0-9]*$"); |
927 | 62 | std::smatch match; | 62 | std::smatch match; |
928 | 63 | if (std::regex_match(instancename, match, instanceregex)) | 63 | if (std::regex_match(instancename, match, instanceregex)) |
929 | @@ -86,11 +86,10 @@ | |||
930 | 86 | } | 86 | } |
931 | 87 | 87 | ||
932 | 88 | g_debug("Overall there are %d instances: %s", int(instanceset.size()), | 88 | g_debug("Overall there are %d instances: %s", int(instanceset.size()), |
938 | 89 | std::accumulate(instanceset.begin(), instanceset.end(), std::string{}, | 89 | std::accumulate(instanceset.begin(), instanceset.end(), std::string{}, [](const std::string& instr, |
939 | 90 | [](const std::string &instr, std::string instance) { | 90 | std::string instance) { |
940 | 91 | return instr.empty() ? instance : instr + ", " + instance; | 91 | return instr.empty() ? instance : instr + ", " + instance; |
941 | 92 | }) | 92 | }).c_str()); |
937 | 93 | .c_str()); | ||
942 | 94 | 93 | ||
943 | 95 | /* Convert to Applications */ | 94 | /* Convert to Applications */ |
944 | 96 | std::list<std::shared_ptr<Application>> apps; | 95 | std::list<std::shared_ptr<Application>> apps; |
945 | @@ -127,6 +126,16 @@ | |||
946 | 127 | return list; | 126 | return list; |
947 | 128 | } | 127 | } |
948 | 129 | 128 | ||
949 | 129 | void Registry::setManager(const std::shared_ptr<Manager>& manager, const std::shared_ptr<Registry>& registry) | ||
950 | 130 | { | ||
951 | 131 | Registry::Impl::setManager(manager, registry); | ||
952 | 132 | } | ||
953 | 133 | |||
954 | 134 | void Registry::clearManager() | ||
955 | 135 | { | ||
956 | 136 | impl->clearManager(); | ||
957 | 137 | } | ||
958 | 138 | |||
959 | 130 | std::shared_ptr<Registry> defaultRegistry; | 139 | std::shared_ptr<Registry> defaultRegistry; |
960 | 131 | std::shared_ptr<Registry> Registry::getDefault() | 140 | std::shared_ptr<Registry> Registry::getDefault() |
961 | 132 | { | 141 | { |
962 | @@ -143,5 +152,39 @@ | |||
963 | 143 | defaultRegistry.reset(); | 152 | defaultRegistry.reset(); |
964 | 144 | } | 153 | } |
965 | 145 | 154 | ||
966 | 155 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& Registry::appStarted( | ||
967 | 156 | const std::shared_ptr<Registry>& reg) | ||
968 | 157 | { | ||
969 | 158 | return reg->impl->appStarted(reg); | ||
970 | 159 | } | ||
971 | 160 | |||
972 | 161 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& Registry::appStopped( | ||
973 | 162 | const std::shared_ptr<Registry>& reg) | ||
974 | 163 | { | ||
975 | 164 | return reg->impl->appStopped(reg); | ||
976 | 165 | } | ||
977 | 166 | |||
978 | 167 | core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, Registry::FailureType>& | ||
979 | 168 | Registry::appFailed(const std::shared_ptr<Registry>& reg) | ||
980 | 169 | { | ||
981 | 170 | return reg->impl->appFailed(reg); | ||
982 | 171 | } | ||
983 | 172 | |||
984 | 173 | core::Signal<const std::shared_ptr<Application>&, | ||
985 | 174 | const std::shared_ptr<Application::Instance>&, | ||
986 | 175 | const std::vector<pid_t>&>& | ||
987 | 176 | Registry::appPaused(const std::shared_ptr<Registry>& reg) | ||
988 | 177 | { | ||
989 | 178 | return reg->impl->appPaused(reg); | ||
990 | 179 | } | ||
991 | 180 | |||
992 | 181 | core::Signal<const std::shared_ptr<Application>&, | ||
993 | 182 | const std::shared_ptr<Application::Instance>&, | ||
994 | 183 | const std::vector<pid_t>&>& | ||
995 | 184 | Registry::appResumed(const std::shared_ptr<Registry>& reg) | ||
996 | 185 | { | ||
997 | 186 | return reg->impl->appResumed(reg); | ||
998 | 187 | } | ||
999 | 188 | |||
1000 | 146 | } // namespace app_launch | 189 | } // namespace app_launch |
1001 | 147 | } // namespace ubuntu | 190 | } // namespace ubuntu |
1002 | 148 | 191 | ||
1003 | === modified file 'libubuntu-app-launch/registry.h' | |||
1004 | --- libubuntu-app-launch/registry.h 2016-06-09 14:55:34 +0000 | |||
1005 | +++ libubuntu-app-launch/registry.h 2017-01-24 04:21:42 +0000 | |||
1006 | @@ -73,28 +73,137 @@ | |||
1007 | 73 | */ | 73 | */ |
1008 | 74 | static std::list<std::shared_ptr<Application>> installedApps(std::shared_ptr<Registry> registry = getDefault()); | 74 | static std::list<std::shared_ptr<Application>> installedApps(std::shared_ptr<Registry> registry = getDefault()); |
1009 | 75 | 75 | ||
1010 | 76 | #if 0 /* TODO -- In next MR */ | ||
1011 | 77 | /* Signals to discover what is happening to apps */ | 76 | /* Signals to discover what is happening to apps */ |
1020 | 78 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> appStarted; | 77 | /** Get the signal object that is signaled when an application has been |
1021 | 79 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> appStopped; | 78 | started. |
1022 | 80 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, FailureType> appFailed; | 79 | |
1023 | 81 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> appPaused; | 80 | \note This signal handler is activated on the UAL thread |
1024 | 82 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> appResumed; | 81 | |
1025 | 83 | 82 | \param reg Registry to get the handler from | |
1026 | 84 | /* The Application Manager, almost always if you're not Unity8, don't | 83 | */ |
1027 | 85 | use this API. Testing is a special case. */ | 84 | static core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& appStarted( |
1028 | 85 | const std::shared_ptr<Registry>& reg = getDefault()); | ||
1029 | 86 | |||
1030 | 87 | /** Get the signal object that is signaled when an application has stopped. | ||
1031 | 88 | |||
1032 | 89 | \note This signal handler is activated on the UAL thread | ||
1033 | 90 | |||
1034 | 91 | \param reg Registry to get the handler from | ||
1035 | 92 | */ | ||
1036 | 93 | static core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& appStopped( | ||
1037 | 94 | const std::shared_ptr<Registry>& reg = getDefault()); | ||
1038 | 95 | |||
1039 | 96 | /** Get the signal object that is signaled when an application has failed. | ||
1040 | 97 | |||
1041 | 98 | \note This signal handler is activated on the UAL thread | ||
1042 | 99 | |||
1043 | 100 | \param reg Registry to get the handler from | ||
1044 | 101 | */ | ||
1045 | 102 | static core:: | ||
1046 | 103 | Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, FailureType>& | ||
1047 | 104 | appFailed(const std::shared_ptr<Registry>& reg = getDefault()); | ||
1048 | 105 | |||
1049 | 106 | /** Get the signal object that is signaled when an application has been | ||
1050 | 107 | paused. | ||
1051 | 108 | |||
1052 | 109 | \note This signal handler is activated on the UAL thread | ||
1053 | 110 | |||
1054 | 111 | \param reg Registry to get the handler from | ||
1055 | 112 | */ | ||
1056 | 113 | static core::Signal<const std::shared_ptr<Application>&, | ||
1057 | 114 | const std::shared_ptr<Application::Instance>&, | ||
1058 | 115 | const std::vector<pid_t>&>& | ||
1059 | 116 | appPaused(const std::shared_ptr<Registry>& reg = getDefault()); | ||
1060 | 117 | |||
1061 | 118 | /** Get the signal object that is signaled when an application has been | ||
1062 | 119 | resumed. | ||
1063 | 120 | |||
1064 | 121 | \note This signal handler is activated on the UAL thread | ||
1065 | 122 | |||
1066 | 123 | \param reg Registry to get the handler from | ||
1067 | 124 | */ | ||
1068 | 125 | static core::Signal<const std::shared_ptr<Application>&, | ||
1069 | 126 | const std::shared_ptr<Application::Instance>&, | ||
1070 | 127 | const std::vector<pid_t>&>& | ||
1071 | 128 | appResumed(const std::shared_ptr<Registry>& reg = getDefault()); | ||
1072 | 129 | |||
1073 | 130 | /** The Application Manager, almost always if you're not Unity8, don't | ||
1074 | 131 | use this API. Testing is a special case. Subclass this interface and | ||
1075 | 132 | implement these functions. | ||
1076 | 133 | |||
1077 | 134 | Each function here is being passed a function object that takes a boolean | ||
1078 | 135 | to reply. This will accept or reject the request. The function object | ||
1079 | 136 | can be copied to another thread and executed if needed. | ||
1080 | 137 | |||
1081 | 138 | The reply is required for the application to start. It will block (not | ||
1082 | 139 | currently implemented) until approval is given. If there are multiple requests | ||
1083 | 140 | sent they may be replied out of order if desired. | ||
1084 | 141 | */ | ||
1085 | 86 | class Manager | 142 | class Manager |
1086 | 87 | { | 143 | { |
1089 | 88 | virtual bool focusRequest (std::shared_ptr<Application> app, std::shared_ptr<Application::Instance> instance) = 0; | 144 | public: |
1090 | 89 | virtual bool startingRequest (std::shared_ptr<Application> app, std::shared_ptr<Application::Instance> instance) = 0; | 145 | /** Application wishes to startup |
1091 | 146 | |||
1092 | 147 | \note This signal handler is activated on the UAL thread | ||
1093 | 148 | |||
1094 | 149 | \param app Application requesting startup | ||
1095 | 150 | \param instance Instance of the app, always valid but not useful | ||
1096 | 151 | unless mulit-instance app. | ||
1097 | 152 | \param reply Function object to reply if it is allowed to start | ||
1098 | 153 | */ | ||
1099 | 154 | virtual void startingRequest(const std::shared_ptr<Application>& app, | ||
1100 | 155 | const std::shared_ptr<Application::Instance>& instance, | ||
1101 | 156 | std::function<void(bool)> reply) = 0; | ||
1102 | 157 | |||
1103 | 158 | /** Application wishes to have focus. Usually this occurs when | ||
1104 | 159 | a URL for the application is activated and the running app is | ||
1105 | 160 | requested. | ||
1106 | 161 | |||
1107 | 162 | \note This signal handler is activated on the UAL thread | ||
1108 | 163 | |||
1109 | 164 | \param app Application requesting focus | ||
1110 | 165 | \param instance Instance of the app, always valid but not useful | ||
1111 | 166 | unless mulit-instance app. | ||
1112 | 167 | \param reply Function object to reply if it is allowed to focus | ||
1113 | 168 | */ | ||
1114 | 169 | virtual void focusRequest(const std::shared_ptr<Application>& app, | ||
1115 | 170 | const std::shared_ptr<Application::Instance>& instance, | ||
1116 | 171 | std::function<void(bool)> reply) = 0; | ||
1117 | 172 | |||
1118 | 173 | /** Application wishes to resume. Usually this occurs when | ||
1119 | 174 | a URL for the application is activated and the running app is | ||
1120 | 175 | requested. | ||
1121 | 176 | |||
1122 | 177 | \note This signal handler is activated on the UAL thread | ||
1123 | 178 | |||
1124 | 179 | \param app Application requesting resume | ||
1125 | 180 | \param instance Instance of the app, always valid but not useful | ||
1126 | 181 | unless mulit-instance app. | ||
1127 | 182 | \param reply Function object to reply if it is allowed to resume | ||
1128 | 183 | */ | ||
1129 | 184 | virtual void resumeRequest(const std::shared_ptr<Application>& app, | ||
1130 | 185 | const std::shared_ptr<Application::Instance>& instance, | ||
1131 | 186 | std::function<void(bool)> reply) = 0; | ||
1132 | 90 | 187 | ||
1133 | 91 | protected: | 188 | protected: |
1134 | 92 | Manager() = default; | 189 | Manager() = default; |
1135 | 190 | /* virtual ~Manager() = default; | ||
1136 | 191 | TODO: Next ABI break */ | ||
1137 | 93 | }; | 192 | }; |
1138 | 94 | 193 | ||
1142 | 95 | void setManager (Manager* manager); | 194 | /** Set the manager of applications, which gives permissions for them to |
1143 | 96 | void clearManager (); | 195 | start and gain focus. In almost all cases this should be Unity8 as it |
1144 | 97 | #endif | 196 | will be controlling applications. |
1145 | 197 | |||
1146 | 198 | This function will failure if there is already a manager set. | ||
1147 | 199 | |||
1148 | 200 | \param manager A reference to the Manager object to call | ||
1149 | 201 | \param registry Registry to register the manager on | ||
1150 | 202 | */ | ||
1151 | 203 | static void setManager(const std::shared_ptr<Manager>& manager, const std::shared_ptr<Registry>& registry); | ||
1152 | 204 | |||
1153 | 205 | /** Remove the current manager on the registry */ | ||
1154 | 206 | void clearManager(); | ||
1155 | 98 | 207 | ||
1156 | 99 | /* Helper Lists */ | 208 | /* Helper Lists */ |
1157 | 100 | /** Get a list of all the helpers for a given helper type | 209 | /** Get a list of all the helpers for a given helper type |
1158 | 101 | 210 | ||
1159 | === modified file 'libubuntu-app-launch/ubuntu-app-launch.cpp' | |||
1160 | --- libubuntu-app-launch/ubuntu-app-launch.cpp 2016-11-10 15:39:08 +0000 | |||
1161 | +++ libubuntu-app-launch/ubuntu-app-launch.cpp 2017-01-24 04:21:42 +0000 | |||
1162 | @@ -39,6 +39,7 @@ | |||
1163 | 39 | #include "appid.h" | 39 | #include "appid.h" |
1164 | 40 | #include "registry.h" | 40 | #include "registry.h" |
1165 | 41 | #include "registry-impl.h" | 41 | #include "registry-impl.h" |
1166 | 42 | #include <algorithm> | ||
1167 | 42 | 43 | ||
1168 | 43 | static void free_helper (gpointer value); | 44 | static void free_helper (gpointer value); |
1169 | 44 | int kill (pid_t pid, int signal) noexcept; | 45 | int kill (pid_t pid, int signal) noexcept; |
1170 | @@ -271,504 +272,365 @@ | |||
1171 | 271 | gpointer user_data; | 272 | gpointer user_data; |
1172 | 272 | }; | 273 | }; |
1173 | 273 | 274 | ||
1253 | 274 | /* The data we keep for each failed observer */ | 275 | /* Function to take a work function and have it execute on a given |
1254 | 275 | typedef struct _paused_resumed_observer_t paused_resumed_observer_t; | 276 | GMainContext */ |
1255 | 276 | struct _paused_resumed_observer_t { | 277 | static void executeOnContext (const std::shared_ptr<GMainContext>& context, std::function<void()> work) |
1256 | 277 | GDBusConnection * conn; | 278 | { |
1257 | 278 | guint sighandle; | 279 | if (!context) { |
1258 | 279 | UbuntuAppLaunchAppPausedResumedObserver func; | 280 | work(); |
1259 | 280 | gpointer user_data; | 281 | return; |
1260 | 281 | const gchar * lttng_signal; | 282 | } |
1261 | 282 | }; | 283 | |
1262 | 283 | 284 | auto heapWork = new std::function<void()>(work); | |
1263 | 284 | /* The lists of Observers */ | 285 | |
1264 | 285 | static GList * starting_array = NULL; | 286 | auto source = std::shared_ptr<GSource>(g_idle_source_new(), [](GSource* src) { g_clear_pointer(&src, g_source_unref); }); |
1265 | 286 | static GList * started_array = NULL; | 287 | g_source_set_callback(source.get(), |
1266 | 287 | static GList * stop_array = NULL; | 288 | [](gpointer data) { |
1267 | 288 | static GList * focus_array = NULL; | 289 | auto heapWork = static_cast<std::function<void()>*>(data); |
1268 | 289 | static GList * resume_array = NULL; | 290 | (*heapWork)(); |
1269 | 290 | static GList * failed_array = NULL; | 291 | return G_SOURCE_REMOVE; |
1270 | 291 | static GList * paused_array = NULL; | 292 | }, |
1271 | 292 | static GList * resumed_array = NULL; | 293 | heapWork, |
1272 | 293 | 294 | [](gpointer data) { | |
1273 | 294 | static void | 295 | auto heapWork = static_cast<std::function<void()>*>(data); |
1274 | 295 | observer_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | 296 | delete heapWork; |
1275 | 296 | { | 297 | }); |
1276 | 297 | observer_t * observer = (observer_t *)user_data; | 298 | |
1277 | 298 | 299 | g_source_attach(source.get(), context.get()); | |
1278 | 299 | const gchar * signalname = NULL; | 300 | } |
1279 | 300 | g_variant_get_child(params, 0, "&s", &signalname); | 301 | |
1280 | 301 | 302 | /** A handy helper function that is based of a function to get | |
1281 | 302 | ual_tracepoint(observer_start, signalname); | 303 | a signal and put it into a map. */ |
1282 | 303 | 304 | template <core::Signal<const std::shared_ptr<ubuntu::app_launch::Application>&, const std::shared_ptr<ubuntu::app_launch::Application::Instance>&>& (*getSignal)(const std::shared_ptr<ubuntu::app_launch::Registry>&)> | |
1283 | 304 | gchar * env = NULL; | 305 | static gboolean |
1284 | 305 | GVariant * envs = g_variant_get_child_value(params, 1); | 306 | observer_add (UbuntuAppLaunchAppObserver observer, gpointer user_data, std::map<std::pair<UbuntuAppLaunchAppObserver, gpointer>, core::ScopedConnection> &observers) |
1285 | 306 | GVariantIter iter; | 307 | { |
1286 | 307 | g_variant_iter_init(&iter, envs); | 308 | auto context = std::shared_ptr<GMainContext>(g_main_context_ref_thread_default(), [](GMainContext * context) { g_clear_pointer(&context, g_main_context_unref); }); |
1287 | 308 | 309 | ||
1288 | 309 | gboolean job_found = FALSE; | 310 | observers.emplace(std::make_pair( |
1289 | 310 | gboolean job_legacy = FALSE; | 311 | std::make_pair(observer, user_data), |
1290 | 311 | gchar * instance = NULL; | 312 | core::ScopedConnection( |
1291 | 312 | 313 | getSignal(ubuntu::app_launch::Registry::getDefault()) | |
1292 | 313 | while (g_variant_iter_loop(&iter, "s", &env)) { | 314 | .connect([context, observer, user_data](std::shared_ptr<ubuntu::app_launch::Application> app, std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { |
1293 | 314 | if (g_strcmp0(env, "JOB=application-click") == 0) { | 315 | std::string appid = app->appId(); |
1294 | 315 | job_found = TRUE; | 316 | executeOnContext(context, [appid, observer, user_data]() { |
1295 | 316 | } else if (g_strcmp0(env, "JOB=application-legacy") == 0) { | 317 | observer(appid.c_str(), user_data); |
1296 | 317 | job_found = TRUE; | 318 | }); |
1297 | 318 | job_legacy = TRUE; | 319 | }) |
1298 | 319 | } else if (g_strcmp0(env, "JOB=application-snap") == 0) { | 320 | ) |
1299 | 320 | job_found = TRUE; | 321 | )); |
1300 | 321 | job_legacy = TRUE; | 322 | |
1301 | 322 | } else if (g_str_has_prefix(env, "INSTANCE=")) { | 323 | return TRUE; |
1302 | 323 | instance = g_strdup(env + strlen("INSTANCE=")); | 324 | } |
1303 | 324 | } | 325 | |
1304 | 325 | } | 326 | /** A handy helper to delete items from an observer map */ |
1305 | 326 | 327 | template<typename observertype> | |
1306 | 327 | g_variant_unref(envs); | 328 | static gboolean |
1307 | 328 | 329 | observer_delete (observertype observer, gpointer user_data, std::map<std::pair<observertype, gpointer>, core::ScopedConnection> &observers) | |
1308 | 329 | if (job_legacy && instance != NULL) { | 330 | { |
1309 | 330 | gchar * dash = g_strrstr(instance, "-"); | 331 | auto iter = observers.find(std::make_pair(observer, user_data)); |
1310 | 331 | if (dash != NULL) { | 332 | |
1311 | 332 | dash[0] = '\0'; | 333 | if (iter == observers.end()) { |
1233 | 333 | } | ||
1234 | 334 | } | ||
1235 | 335 | |||
1236 | 336 | if (job_found && instance != NULL) { | ||
1237 | 337 | observer->func(instance, observer->user_data); | ||
1238 | 338 | } | ||
1239 | 339 | |||
1240 | 340 | ual_tracepoint(observer_finish, signalname); | ||
1241 | 341 | |||
1242 | 342 | g_free(instance); | ||
1243 | 343 | } | ||
1244 | 344 | |||
1245 | 345 | /* Creates the observer structure and registers for the signal with | ||
1246 | 346 | GDBus so that we can get a callback */ | ||
1247 | 347 | static gboolean | ||
1248 | 348 | add_app_generic (UbuntuAppLaunchAppObserver observer, gpointer user_data, const gchar * signal, GList ** list) | ||
1249 | 349 | { | ||
1250 | 350 | GDBusConnection * conn = gdbus_upstart_ref(); | ||
1251 | 351 | |||
1252 | 352 | if (conn == NULL) { | ||
1312 | 353 | return FALSE; | 334 | return FALSE; |
1313 | 354 | } | 335 | } |
1314 | 355 | 336 | ||
1334 | 356 | observer_t * observert = g_new0(observer_t, 1); | 337 | observers.erase(iter); |
1316 | 357 | |||
1317 | 358 | observert->conn = conn; | ||
1318 | 359 | observert->func = observer; | ||
1319 | 360 | observert->user_data = user_data; | ||
1320 | 361 | |||
1321 | 362 | *list = g_list_prepend(*list, observert); | ||
1322 | 363 | |||
1323 | 364 | observert->sighandle = g_dbus_connection_signal_subscribe(conn, | ||
1324 | 365 | NULL, /* sender */ | ||
1325 | 366 | DBUS_INTERFACE_UPSTART, /* interface */ | ||
1326 | 367 | "EventEmitted", /* signal */ | ||
1327 | 368 | DBUS_PATH_UPSTART, /* path */ | ||
1328 | 369 | signal, /* arg0 */ | ||
1329 | 370 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
1330 | 371 | observer_cb, | ||
1331 | 372 | observert, | ||
1332 | 373 | NULL); /* user data destroy */ | ||
1333 | 374 | |||
1335 | 375 | return TRUE; | 338 | return TRUE; |
1336 | 376 | } | 339 | } |
1337 | 377 | 340 | ||
1338 | 341 | /** Map of all the observers listening for app started */ | ||
1339 | 342 | static std::map<std::pair<UbuntuAppLaunchAppObserver, gpointer>, core::ScopedConnection> appStartedObservers; | ||
1340 | 343 | |||
1341 | 378 | gboolean | 344 | gboolean |
1342 | 379 | ubuntu_app_launch_observer_add_app_started (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 345 | ubuntu_app_launch_observer_add_app_started (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1343 | 380 | { | 346 | { |
1346 | 381 | return add_app_generic(observer, user_data, "started", &started_array); | 347 | return observer_add<&ubuntu::app_launch::Registry::appStarted>(observer, user_data, appStartedObservers); |
1347 | 382 | } | 348 | } |
1348 | 349 | |||
1349 | 350 | gboolean | ||
1350 | 351 | ubuntu_app_launch_observer_delete_app_started (UbuntuAppLaunchAppObserver observer, gpointer user_data) | ||
1351 | 352 | { | ||
1352 | 353 | return observer_delete<UbuntuAppLaunchAppObserver>(observer, user_data, appStartedObservers); | ||
1353 | 354 | } | ||
1354 | 355 | |||
1355 | 356 | /* Map of all the observers listening for app stopped */ | ||
1356 | 357 | static std::map<std::pair<UbuntuAppLaunchAppObserver, gpointer>, core::ScopedConnection> appStoppedObservers; | ||
1357 | 383 | 358 | ||
1358 | 384 | gboolean | 359 | gboolean |
1359 | 385 | ubuntu_app_launch_observer_add_app_stop (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 360 | ubuntu_app_launch_observer_add_app_stop (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1360 | 386 | { | 361 | { |
1419 | 387 | return add_app_generic(observer, user_data, "stopped", &stop_array); | 362 | return observer_add<&ubuntu::app_launch::Registry::appStopped>(observer, user_data, appStoppedObservers); |
1420 | 388 | } | 363 | } |
1421 | 389 | 364 | ||
1422 | 390 | /* Creates the observer structure and registers for the signal with | 365 | gboolean |
1423 | 391 | GDBus so that we can get a callback */ | 366 | ubuntu_app_launch_observer_delete_app_stop (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1424 | 392 | static gboolean | 367 | { |
1425 | 393 | add_session_generic (UbuntuAppLaunchAppObserver observer, gpointer user_data, const gchar * signal, GList ** list, GDBusSignalCallback session_cb) | 368 | return observer_delete<UbuntuAppLaunchAppObserver>(observer, user_data, appStoppedObservers); |
1426 | 394 | { | 369 | } |
1427 | 395 | GDBusConnection * conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | 370 | |
1428 | 396 | 371 | /** Class to implement the Registry::Manager interface for the C code | |
1429 | 397 | if (conn == NULL) { | 372 | using a GLib mainloop. */ |
1430 | 398 | return FALSE; | 373 | class CManager : public ubuntu::app_launch::Registry::Manager |
1431 | 399 | } | 374 | { |
1432 | 400 | 375 | public: | |
1433 | 401 | observer_t * observert = g_new0(observer_t, 1); | 376 | CManager () { |
1434 | 402 | 377 | g_debug("Creating the CManager object"); | |
1435 | 403 | observert->conn = conn; | 378 | } |
1436 | 404 | observert->func = observer; | 379 | virtual ~CManager() { |
1437 | 405 | observert->user_data = user_data; | 380 | g_debug("Removing the shared the CManager object"); |
1438 | 406 | 381 | } | |
1439 | 407 | *list = g_list_prepend(*list, observert); | 382 | |
1440 | 408 | 383 | void startingRequest(const std::shared_ptr<ubuntu::app_launch::Application>& app, | |
1441 | 409 | observert->sighandle = g_dbus_connection_signal_subscribe(conn, | 384 | const std::shared_ptr<ubuntu::app_launch::Application::Instance>& instance, |
1442 | 410 | NULL, /* sender */ | 385 | std::function<void(bool)> reply) override { |
1443 | 411 | "com.canonical.UbuntuAppLaunch", /* interface */ | 386 | requestImpl(app, instance, reply, "starting", startingList); |
1444 | 412 | signal, /* signal */ | 387 | } |
1445 | 413 | "/", /* path */ | 388 | |
1446 | 414 | NULL, /* arg0 */ | 389 | void focusRequest(const std::shared_ptr<ubuntu::app_launch::Application>& app, |
1447 | 415 | G_DBUS_SIGNAL_FLAGS_NONE, | 390 | const std::shared_ptr<ubuntu::app_launch::Application::Instance>& instance, |
1448 | 416 | session_cb, | 391 | std::function<void(bool)> reply) override { |
1449 | 417 | observert, | 392 | requestImpl(app, instance, reply, "focus", focusList); |
1450 | 418 | NULL); /* user data destroy */ | 393 | } |
1451 | 419 | 394 | ||
1452 | 420 | return TRUE; | 395 | void resumeRequest(const std::shared_ptr<ubuntu::app_launch::Application> &app, |
1453 | 421 | } | 396 | const std::shared_ptr<ubuntu::app_launch::Application::Instance> &instance, |
1454 | 422 | 397 | std::function<void(bool)> reply) override { | |
1455 | 423 | /* Generic handler for a bunch of our signals */ | 398 | requestImpl(app, instance, reply, "resume", resumeList); |
1456 | 424 | static inline void | 399 | } |
1457 | 425 | generic_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | 400 | |
1458 | 426 | { | 401 | private: |
1459 | 427 | observer_t * observer = (observer_t *)user_data; | 402 | /** The Data that we track on an observer. It is the functions to |
1460 | 428 | const gchar * appid = NULL; | 403 | call, the user data and the context to call it on. */ |
1461 | 429 | 404 | struct ObserverData { | |
1462 | 430 | if (observer->func != NULL) { | 405 | UbuntuAppLaunchAppObserver observer; |
1463 | 431 | g_variant_get(params, "(&s)", &appid); | 406 | gpointer user_data; |
1464 | 432 | observer->func(appid, observer->user_data); | 407 | std::shared_ptr<GMainContext> context; |
1465 | 433 | } | 408 | |
1466 | 434 | } | 409 | /** Handy constructor to get the context in one place */ |
1467 | 435 | 410 | ObserverData(UbuntuAppLaunchAppObserver obs, gpointer ud) | |
1468 | 436 | /* Handle the focus signal when it occurs, call the observer */ | 411 | : observer(obs) |
1469 | 437 | static void | 412 | , user_data(ud) { |
1470 | 438 | focus_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | 413 | context = std::shared_ptr<GMainContext>(g_main_context_ref_thread_default(), [](GMainContext * context) { g_clear_pointer(&context, g_main_context_unref); }); |
1471 | 439 | { | 414 | } |
1472 | 440 | ual_tracepoint(observer_start, "focus"); | 415 | }; |
1473 | 441 | 416 | ||
1474 | 442 | generic_signal_cb(conn, sender, object, interface, signal, params, user_data); | 417 | std::list<ObserverData> focusList; /**< List of observers on the focus signal */ |
1475 | 443 | 418 | std::list<ObserverData> resumeList; /**< List of observers on the resume signal */ | |
1476 | 444 | ual_tracepoint(observer_finish, "focus"); | 419 | std::list<ObserverData> startingList; /**< List of observers on the starting signal */ |
1477 | 420 | |||
1478 | 421 | /** Removes an observer from a specified list */ | ||
1479 | 422 | bool removeObserver (std::list<ObserverData> &list, UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1480 | 423 | auto iter = std::find_if(list.begin(), list.end(), [observer, user_data](const ObserverData &data) { | ||
1481 | 424 | return data.observer == observer && data.user_data == user_data; | ||
1482 | 425 | }); | ||
1483 | 426 | |||
1484 | 427 | if (iter == list.end()) { | ||
1485 | 428 | return false; | ||
1486 | 429 | } | ||
1487 | 430 | |||
1488 | 431 | list.erase(iter); | ||
1489 | 432 | return true; | ||
1490 | 433 | } | ||
1491 | 434 | |||
1492 | 435 | /** Implements a request for a specified list by calling each observer and then the reply */ | ||
1493 | 436 | inline void requestImpl ( const std::shared_ptr<ubuntu::app_launch::Application> &app, | ||
1494 | 437 | const std::shared_ptr<ubuntu::app_launch::Application::Instance> &instance, | ||
1495 | 438 | std::function<void(bool)> reply, | ||
1496 | 439 | const std::string& name, | ||
1497 | 440 | std::list<ObserverData>& list) { | ||
1498 | 441 | std::string sappid = app->appId(); | ||
1499 | 442 | g_debug("CManager %s: %s", name.c_str(), sappid.c_str()); | ||
1500 | 443 | |||
1501 | 444 | for (const auto &data : list) { | ||
1502 | 445 | executeOnContext(data.context, [data, sappid]() { | ||
1503 | 446 | data.observer(sappid.c_str(), data.user_data); | ||
1504 | 447 | }); | ||
1505 | 448 | } | ||
1506 | 449 | |||
1507 | 450 | reply(true); | ||
1508 | 451 | } | ||
1509 | 452 | |||
1510 | 453 | public: | ||
1511 | 454 | void addFocus (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1512 | 455 | focusList.emplace_back(ObserverData(observer, user_data)); | ||
1513 | 456 | } | ||
1514 | 457 | void addResume (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1515 | 458 | resumeList.emplace_back(ObserverData(observer, user_data)); | ||
1516 | 459 | } | ||
1517 | 460 | void addStarting (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1518 | 461 | startingList.emplace_back(ObserverData(observer, user_data)); | ||
1519 | 462 | } | ||
1520 | 463 | bool deleteFocus (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1521 | 464 | return removeObserver(focusList, observer, user_data); | ||
1522 | 465 | } | ||
1523 | 466 | bool deleteResume (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1524 | 467 | return removeObserver(resumeList, observer, user_data); | ||
1525 | 468 | } | ||
1526 | 469 | bool deleteStarting (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1527 | 470 | return removeObserver(startingList, observer, user_data); | ||
1528 | 471 | } | ||
1529 | 472 | }; | ||
1530 | 473 | |||
1531 | 474 | /** Weak pointer to the CManager if it is still in use. If it gets free'd by | ||
1532 | 475 | the registry we're okay with that. */ | ||
1533 | 476 | static std::weak_ptr<CManager> cmanager; | ||
1534 | 477 | |||
1535 | 478 | /** Function to create the CManager if it doesn't currently exist. Otherwise | ||
1536 | 479 | just return a lock to it */ | ||
1537 | 480 | static std::shared_ptr<CManager> | ||
1538 | 481 | ensure_cmanager () | ||
1539 | 482 | { | ||
1540 | 483 | auto retval = cmanager.lock(); | ||
1541 | 484 | |||
1542 | 485 | if (!retval) { | ||
1543 | 486 | retval = std::make_shared<CManager>(); | ||
1544 | 487 | ubuntu::app_launch::Registry::setManager(retval, ubuntu::app_launch::Registry::getDefault()); | ||
1545 | 488 | cmanager = retval; | ||
1546 | 489 | } | ||
1547 | 490 | |||
1548 | 491 | return retval; | ||
1549 | 445 | } | 492 | } |
1550 | 446 | 493 | ||
1551 | 447 | gboolean | 494 | gboolean |
1552 | 448 | ubuntu_app_launch_observer_add_app_focus (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 495 | ubuntu_app_launch_observer_add_app_focus (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1553 | 449 | { | 496 | { |
1555 | 450 | return add_session_generic(observer, user_data, "UnityFocusRequest", &focus_array, focus_signal_cb); | 497 | auto manager = ensure_cmanager(); |
1556 | 498 | manager->addFocus(observer, user_data); | ||
1557 | 499 | return TRUE; | ||
1558 | 451 | } | 500 | } |
1559 | 452 | 501 | ||
1563 | 453 | /* Handle the resume signal when it occurs, call the observer, then send a signal back when we're done */ | 502 | gboolean |
1564 | 454 | static void | 503 | ubuntu_app_launch_observer_delete_app_focus (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1562 | 455 | resume_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | ||
1565 | 456 | { | 504 | { |
1585 | 457 | ual_tracepoint(observer_start, "resume"); | 505 | auto manager = ensure_cmanager(); |
1586 | 458 | 506 | return manager->deleteFocus(observer, user_data) ? TRUE : FALSE; | |
1568 | 459 | generic_signal_cb(conn, sender, object, interface, signal, params, user_data); | ||
1569 | 460 | |||
1570 | 461 | GError * error = NULL; | ||
1571 | 462 | g_dbus_connection_emit_signal(conn, | ||
1572 | 463 | sender, /* destination */ | ||
1573 | 464 | "/", /* path */ | ||
1574 | 465 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
1575 | 466 | "UnityResumeResponse", /* signal */ | ||
1576 | 467 | params, /* params, the same */ | ||
1577 | 468 | &error); | ||
1578 | 469 | |||
1579 | 470 | if (error != NULL) { | ||
1580 | 471 | g_warning("Unable to emit response signal: %s", error->message); | ||
1581 | 472 | g_error_free(error); | ||
1582 | 473 | } | ||
1583 | 474 | |||
1584 | 475 | ual_tracepoint(observer_finish, "resume"); | ||
1587 | 476 | } | 507 | } |
1588 | 477 | 508 | ||
1589 | 478 | gboolean | 509 | gboolean |
1590 | 479 | ubuntu_app_launch_observer_add_app_resume (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 510 | ubuntu_app_launch_observer_add_app_resume (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1591 | 480 | { | 511 | { |
1593 | 481 | return add_session_generic(observer, user_data, "UnityResumeRequest", &resume_array, resume_signal_cb); | 512 | auto manager = ensure_cmanager(); |
1594 | 513 | manager->addResume(observer, user_data); | ||
1595 | 514 | return TRUE; | ||
1596 | 482 | } | 515 | } |
1597 | 483 | 516 | ||
1601 | 484 | /* Handle the starting signal when it occurs, call the observer, then send a signal back when we're done */ | 517 | gboolean |
1602 | 485 | static void | 518 | ubuntu_app_launch_observer_delete_app_resume (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1600 | 486 | starting_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | ||
1603 | 487 | { | 519 | { |
1623 | 488 | ual_tracepoint(observer_start, "starting"); | 520 | auto manager = ensure_cmanager(); |
1624 | 489 | 521 | return manager->deleteResume(observer, user_data) ? TRUE : FALSE; | |
1606 | 490 | generic_signal_cb(conn, sender, object, interface, signal, params, user_data); | ||
1607 | 491 | |||
1608 | 492 | GError * error = NULL; | ||
1609 | 493 | g_dbus_connection_emit_signal(conn, | ||
1610 | 494 | sender, /* destination */ | ||
1611 | 495 | "/", /* path */ | ||
1612 | 496 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
1613 | 497 | "UnityStartingSignal", /* signal */ | ||
1614 | 498 | params, /* params, the same */ | ||
1615 | 499 | &error); | ||
1616 | 500 | |||
1617 | 501 | if (error != NULL) { | ||
1618 | 502 | g_warning("Unable to emit response signal: %s", error->message); | ||
1619 | 503 | g_error_free(error); | ||
1620 | 504 | } | ||
1621 | 505 | |||
1622 | 506 | ual_tracepoint(observer_finish, "starting"); | ||
1625 | 507 | } | 522 | } |
1626 | 508 | 523 | ||
1627 | 509 | gboolean | 524 | gboolean |
1628 | 510 | ubuntu_app_launch_observer_add_app_starting (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 525 | ubuntu_app_launch_observer_add_app_starting (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1629 | 511 | { | 526 | { |
1630 | 527 | auto manager = ensure_cmanager(); | ||
1631 | 512 | ubuntu::app_launch::Registry::Impl::watchingAppStarting(true); | 528 | ubuntu::app_launch::Registry::Impl::watchingAppStarting(true); |
1818 | 513 | return add_session_generic(observer, user_data, "UnityStartingBroadcast", &starting_array, starting_signal_cb); | 529 | manager->addStarting(observer, user_data); |
1819 | 514 | } | 530 | return TRUE; |
1634 | 515 | |||
1635 | 516 | /* Handle the failed signal when it occurs, call the observer */ | ||
1636 | 517 | static void | ||
1637 | 518 | failed_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | ||
1638 | 519 | { | ||
1639 | 520 | failed_observer_t * observer = (failed_observer_t *)user_data; | ||
1640 | 521 | const gchar * appid = NULL; | ||
1641 | 522 | const gchar * typestr = NULL; | ||
1642 | 523 | |||
1643 | 524 | ual_tracepoint(observer_start, "failed"); | ||
1644 | 525 | |||
1645 | 526 | if (observer->func != NULL) { | ||
1646 | 527 | UbuntuAppLaunchAppFailed type = UBUNTU_APP_LAUNCH_APP_FAILED_CRASH; | ||
1647 | 528 | g_variant_get(params, "(&s&s)", &appid, &typestr); | ||
1648 | 529 | |||
1649 | 530 | if (g_strcmp0("crash", typestr) == 0) { | ||
1650 | 531 | type = UBUNTU_APP_LAUNCH_APP_FAILED_CRASH; | ||
1651 | 532 | } else if (g_strcmp0("start-failure", typestr) == 0) { | ||
1652 | 533 | type = UBUNTU_APP_LAUNCH_APP_FAILED_START_FAILURE; | ||
1653 | 534 | } else { | ||
1654 | 535 | g_warning("Application failure type '%s' unknown, reporting as a crash", typestr); | ||
1655 | 536 | } | ||
1656 | 537 | |||
1657 | 538 | observer->func(appid, type, observer->user_data); | ||
1658 | 539 | } | ||
1659 | 540 | |||
1660 | 541 | ual_tracepoint(observer_finish, "failed"); | ||
1661 | 542 | } | ||
1662 | 543 | |||
1663 | 544 | gboolean | ||
1664 | 545 | ubuntu_app_launch_observer_add_app_failed (UbuntuAppLaunchAppFailedObserver observer, gpointer user_data) | ||
1665 | 546 | { | ||
1666 | 547 | GDBusConnection * conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | ||
1667 | 548 | |||
1668 | 549 | if (conn == NULL) { | ||
1669 | 550 | return FALSE; | ||
1670 | 551 | } | ||
1671 | 552 | |||
1672 | 553 | failed_observer_t * observert = g_new0(failed_observer_t, 1); | ||
1673 | 554 | |||
1674 | 555 | observert->conn = conn; | ||
1675 | 556 | observert->func = observer; | ||
1676 | 557 | observert->user_data = user_data; | ||
1677 | 558 | |||
1678 | 559 | failed_array = g_list_prepend(failed_array, observert); | ||
1679 | 560 | |||
1680 | 561 | observert->sighandle = g_dbus_connection_signal_subscribe(conn, | ||
1681 | 562 | NULL, /* sender */ | ||
1682 | 563 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
1683 | 564 | "ApplicationFailed", /* signal */ | ||
1684 | 565 | "/", /* path */ | ||
1685 | 566 | NULL, /* arg0 */ | ||
1686 | 567 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
1687 | 568 | failed_signal_cb, | ||
1688 | 569 | observert, | ||
1689 | 570 | NULL); /* user data destroy */ | ||
1690 | 571 | |||
1691 | 572 | return TRUE; | ||
1692 | 573 | } | ||
1693 | 574 | |||
1694 | 575 | /* Handle the paused signal when it occurs, call the observer */ | ||
1695 | 576 | static void | ||
1696 | 577 | paused_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | ||
1697 | 578 | { | ||
1698 | 579 | paused_resumed_observer_t * observer = (paused_resumed_observer_t *)user_data; | ||
1699 | 580 | |||
1700 | 581 | ual_tracepoint(observer_start, observer->lttng_signal); | ||
1701 | 582 | |||
1702 | 583 | if (observer->func != NULL) { | ||
1703 | 584 | GArray * pidarray = g_array_new(TRUE, TRUE, sizeof(GPid)); | ||
1704 | 585 | GVariant * appid = g_variant_get_child_value(params, 0); | ||
1705 | 586 | GVariant * pids = g_variant_get_child_value(params, 1); | ||
1706 | 587 | guint64 pid; | ||
1707 | 588 | GVariantIter thispid; | ||
1708 | 589 | g_variant_iter_init(&thispid, pids); | ||
1709 | 590 | |||
1710 | 591 | while (g_variant_iter_loop(&thispid, "t", &pid)) { | ||
1711 | 592 | GPid gpid = (GPid)pid; /* Should be a no-op for most architectures, but just in case */ | ||
1712 | 593 | g_array_append_val(pidarray, gpid); | ||
1713 | 594 | } | ||
1714 | 595 | |||
1715 | 596 | observer->func(g_variant_get_string(appid, NULL), (GPid *)pidarray->data, observer->user_data); | ||
1716 | 597 | |||
1717 | 598 | g_array_free(pidarray, TRUE); | ||
1718 | 599 | g_variant_unref(appid); | ||
1719 | 600 | g_variant_unref(pids); | ||
1720 | 601 | } | ||
1721 | 602 | |||
1722 | 603 | ual_tracepoint(observer_finish, observer->lttng_signal); | ||
1723 | 604 | } | ||
1724 | 605 | |||
1725 | 606 | static gboolean | ||
1726 | 607 | paused_resumed_generic (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data, GList ** queue, const gchar * signal_name, const gchar * lttng_signal) | ||
1727 | 608 | { | ||
1728 | 609 | GDBusConnection * conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | ||
1729 | 610 | |||
1730 | 611 | if (conn == NULL) { | ||
1731 | 612 | return FALSE; | ||
1732 | 613 | } | ||
1733 | 614 | |||
1734 | 615 | paused_resumed_observer_t * observert = g_new0(paused_resumed_observer_t, 1); | ||
1735 | 616 | |||
1736 | 617 | observert->conn = conn; | ||
1737 | 618 | observert->func = observer; | ||
1738 | 619 | observert->user_data = user_data; | ||
1739 | 620 | observert->lttng_signal = lttng_signal; | ||
1740 | 621 | |||
1741 | 622 | *queue = g_list_prepend(*queue, observert); | ||
1742 | 623 | |||
1743 | 624 | observert->sighandle = g_dbus_connection_signal_subscribe(conn, | ||
1744 | 625 | NULL, /* sender */ | ||
1745 | 626 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
1746 | 627 | signal_name, /* signal */ | ||
1747 | 628 | "/", /* path */ | ||
1748 | 629 | NULL, /* arg0 */ | ||
1749 | 630 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
1750 | 631 | paused_signal_cb, | ||
1751 | 632 | observert, | ||
1752 | 633 | NULL); /* user data destroy */ | ||
1753 | 634 | |||
1754 | 635 | return TRUE; | ||
1755 | 636 | } | ||
1756 | 637 | |||
1757 | 638 | gboolean | ||
1758 | 639 | ubuntu_app_launch_observer_add_app_paused (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | ||
1759 | 640 | { | ||
1760 | 641 | return paused_resumed_generic(observer, user_data, &paused_array, "ApplicationPaused", "paused"); | ||
1761 | 642 | } | ||
1762 | 643 | |||
1763 | 644 | gboolean | ||
1764 | 645 | ubuntu_app_launch_observer_add_app_resumed (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | ||
1765 | 646 | { | ||
1766 | 647 | return paused_resumed_generic(observer, user_data, &resumed_array, "ApplicationResumed", "resumed"); | ||
1767 | 648 | } | ||
1768 | 649 | |||
1769 | 650 | static gboolean | ||
1770 | 651 | delete_app_generic (UbuntuAppLaunchAppObserver observer, gpointer user_data, GList ** list) | ||
1771 | 652 | { | ||
1772 | 653 | observer_t * observert = NULL; | ||
1773 | 654 | GList * look; | ||
1774 | 655 | |||
1775 | 656 | for (look = *list; look != NULL; look = g_list_next(look)) { | ||
1776 | 657 | observert = (observer_t *)look->data; | ||
1777 | 658 | |||
1778 | 659 | if (observert->func == observer && observert->user_data == user_data) { | ||
1779 | 660 | break; | ||
1780 | 661 | } | ||
1781 | 662 | } | ||
1782 | 663 | |||
1783 | 664 | if (look == NULL) { | ||
1784 | 665 | return FALSE; | ||
1785 | 666 | } | ||
1786 | 667 | |||
1787 | 668 | g_dbus_connection_signal_unsubscribe(observert->conn, observert->sighandle); | ||
1788 | 669 | g_object_unref(observert->conn); | ||
1789 | 670 | |||
1790 | 671 | g_free(observert); | ||
1791 | 672 | *list = g_list_delete_link(*list, look); | ||
1792 | 673 | |||
1793 | 674 | return TRUE; | ||
1794 | 675 | } | ||
1795 | 676 | |||
1796 | 677 | gboolean | ||
1797 | 678 | ubuntu_app_launch_observer_delete_app_started (UbuntuAppLaunchAppObserver observer, gpointer user_data) | ||
1798 | 679 | { | ||
1799 | 680 | return delete_app_generic(observer, user_data, &started_array); | ||
1800 | 681 | } | ||
1801 | 682 | |||
1802 | 683 | gboolean | ||
1803 | 684 | ubuntu_app_launch_observer_delete_app_stop (UbuntuAppLaunchAppObserver observer, gpointer user_data) | ||
1804 | 685 | { | ||
1805 | 686 | return delete_app_generic(observer, user_data, &stop_array); | ||
1806 | 687 | } | ||
1807 | 688 | |||
1808 | 689 | gboolean | ||
1809 | 690 | ubuntu_app_launch_observer_delete_app_resume (UbuntuAppLaunchAppObserver observer, gpointer user_data) | ||
1810 | 691 | { | ||
1811 | 692 | return delete_app_generic(observer, user_data, &resume_array); | ||
1812 | 693 | } | ||
1813 | 694 | |||
1814 | 695 | gboolean | ||
1815 | 696 | ubuntu_app_launch_observer_delete_app_focus (UbuntuAppLaunchAppObserver observer, gpointer user_data) | ||
1816 | 697 | { | ||
1817 | 698 | return delete_app_generic(observer, user_data, &focus_array); | ||
1820 | 699 | } | 531 | } |
1821 | 700 | 532 | ||
1822 | 701 | gboolean | 533 | gboolean |
1823 | 702 | ubuntu_app_launch_observer_delete_app_starting (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 534 | ubuntu_app_launch_observer_delete_app_starting (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1824 | 703 | { | 535 | { |
1825 | 536 | auto manager = ensure_cmanager(); | ||
1826 | 704 | ubuntu::app_launch::Registry::Impl::watchingAppStarting(false); | 537 | ubuntu::app_launch::Registry::Impl::watchingAppStarting(false); |
1828 | 705 | return delete_app_generic(observer, user_data, &starting_array); | 538 | return manager->deleteStarting(observer, user_data) ? TRUE : FALSE; |
1829 | 539 | } | ||
1830 | 540 | |||
1831 | 541 | /* Map of all the observers listening for app stopped */ | ||
1832 | 542 | static std::map<std::pair<UbuntuAppLaunchAppFailedObserver, gpointer>, core::ScopedConnection> appFailedObservers; | ||
1833 | 543 | |||
1834 | 544 | gboolean | ||
1835 | 545 | ubuntu_app_launch_observer_add_app_failed (UbuntuAppLaunchAppFailedObserver observer, gpointer user_data) | ||
1836 | 546 | { | ||
1837 | 547 | auto context = std::shared_ptr<GMainContext>(g_main_context_ref_thread_default(), [](GMainContext * context) { g_clear_pointer(&context, g_main_context_unref); }); | ||
1838 | 548 | |||
1839 | 549 | appFailedObservers.emplace(std::make_pair( | ||
1840 | 550 | std::make_pair(observer, user_data), | ||
1841 | 551 | core::ScopedConnection( | ||
1842 | 552 | ubuntu::app_launch::Registry::appFailed().connect([context, observer, user_data](std::shared_ptr<ubuntu::app_launch::Application> app, std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, ubuntu::app_launch::Registry::FailureType type) { | ||
1843 | 553 | std::string appid = app->appId(); | ||
1844 | 554 | executeOnContext(context, [appid, type, observer, user_data]() { | ||
1845 | 555 | UbuntuAppLaunchAppFailed ctype{UBUNTU_APP_LAUNCH_APP_FAILED_CRASH}; | ||
1846 | 556 | |||
1847 | 557 | switch (type) { | ||
1848 | 558 | case ubuntu::app_launch::Registry::FailureType::CRASH: | ||
1849 | 559 | ctype = UBUNTU_APP_LAUNCH_APP_FAILED_CRASH; | ||
1850 | 560 | break; | ||
1851 | 561 | case ubuntu::app_launch::Registry::FailureType::START_FAILURE: | ||
1852 | 562 | ctype = UBUNTU_APP_LAUNCH_APP_FAILED_START_FAILURE; | ||
1853 | 563 | break; | ||
1854 | 564 | } | ||
1855 | 565 | |||
1856 | 566 | observer(appid.c_str(), ctype, user_data); | ||
1857 | 567 | }); | ||
1858 | 568 | }) | ||
1859 | 569 | ) | ||
1860 | 570 | )); | ||
1861 | 571 | |||
1862 | 572 | return TRUE; | ||
1863 | 706 | } | 573 | } |
1864 | 707 | 574 | ||
1865 | 708 | gboolean | 575 | gboolean |
1866 | 709 | ubuntu_app_launch_observer_delete_app_failed (UbuntuAppLaunchAppFailedObserver observer, gpointer user_data) | 576 | ubuntu_app_launch_observer_delete_app_failed (UbuntuAppLaunchAppFailedObserver observer, gpointer user_data) |
1867 | 710 | { | 577 | { |
1890 | 711 | failed_observer_t * observert = NULL; | 578 | return observer_delete<UbuntuAppLaunchAppFailedObserver>(observer, user_data, appFailedObservers); |
1869 | 712 | GList * look; | ||
1870 | 713 | |||
1871 | 714 | for (look = failed_array; look != NULL; look = g_list_next(look)) { | ||
1872 | 715 | observert = (failed_observer_t *)look->data; | ||
1873 | 716 | |||
1874 | 717 | if (observert->func == observer && observert->user_data == user_data) { | ||
1875 | 718 | break; | ||
1876 | 719 | } | ||
1877 | 720 | } | ||
1878 | 721 | |||
1879 | 722 | if (look == NULL) { | ||
1880 | 723 | return FALSE; | ||
1881 | 724 | } | ||
1882 | 725 | |||
1883 | 726 | g_dbus_connection_signal_unsubscribe(observert->conn, observert->sighandle); | ||
1884 | 727 | g_object_unref(observert->conn); | ||
1885 | 728 | |||
1886 | 729 | g_free(observert); | ||
1887 | 730 | failed_array = g_list_delete_link(failed_array, look); | ||
1888 | 731 | |||
1889 | 732 | return TRUE; | ||
1891 | 733 | } | 579 | } |
1892 | 734 | 580 | ||
1893 | 581 | /** Handy helper for pause and resume here */ | ||
1894 | 582 | template <core::Signal<const std::shared_ptr<ubuntu::app_launch::Application>&, const std::shared_ptr<ubuntu::app_launch::Application::Instance>&, const std::vector<pid_t>&>& (*getSignal)(const std::shared_ptr<ubuntu::app_launch::Registry>&)> | ||
1895 | 735 | static gboolean | 583 | static gboolean |
1897 | 736 | paused_resumed_delete (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data, GList ** list) | 584 | observer_add_pause (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data, std::map<std::pair<UbuntuAppLaunchAppPausedResumedObserver, gpointer>, core::ScopedConnection> &observers) |
1898 | 737 | { | 585 | { |
1919 | 738 | paused_resumed_observer_t * observert = NULL; | 586 | auto context = std::shared_ptr<GMainContext>(g_main_context_ref_thread_default(), [](GMainContext * context) { g_clear_pointer(&context, g_main_context_unref); }); |
1920 | 739 | GList * look; | 587 | |
1921 | 740 | 588 | observers.emplace(std::make_pair( | |
1922 | 741 | for (look = *list; look != NULL; look = g_list_next(look)) { | 589 | std::make_pair(observer, user_data), |
1923 | 742 | observert = (paused_resumed_observer_t *)look->data; | 590 | core::ScopedConnection( |
1924 | 743 | 591 | getSignal(ubuntu::app_launch::Registry::getDefault()) | |
1925 | 744 | if (observert->func == observer && observert->user_data == user_data) { | 592 | .connect([context, observer, user_data](std::shared_ptr<ubuntu::app_launch::Application> app, std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, const std::vector<pid_t> &pids) { |
1926 | 745 | break; | 593 | std::vector<pid_t> lpids = pids; |
1927 | 746 | } | 594 | lpids.emplace_back(0); |
1928 | 747 | } | 595 | |
1929 | 748 | 596 | std::string appid = app->appId(); | |
1930 | 749 | if (look == NULL) { | 597 | |
1931 | 750 | return FALSE; | 598 | executeOnContext(context, [appid, observer, user_data, lpids]() { |
1932 | 751 | } | 599 | observer(appid.c_str(), (int *)(lpids.data()), user_data); |
1933 | 752 | 600 | }); | |
1934 | 753 | g_dbus_connection_signal_unsubscribe(observert->conn, observert->sighandle); | 601 | }) |
1935 | 754 | g_object_unref(observert->conn); | 602 | ) |
1936 | 755 | 603 | )); | |
1917 | 756 | g_free(observert); | ||
1918 | 757 | *list = g_list_delete_link(*list, look); | ||
1937 | 758 | 604 | ||
1938 | 759 | return TRUE; | 605 | return TRUE; |
1939 | 760 | } | 606 | } |
1940 | 761 | 607 | ||
1941 | 608 | static std::map<std::pair<UbuntuAppLaunchAppPausedResumedObserver, gpointer>, core::ScopedConnection> appPausedObservers; | ||
1942 | 609 | |||
1943 | 610 | gboolean | ||
1944 | 611 | ubuntu_app_launch_observer_add_app_paused (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | ||
1945 | 612 | { | ||
1946 | 613 | return observer_add_pause<&ubuntu::app_launch::Registry::appPaused>(observer, user_data, appPausedObservers); | ||
1947 | 614 | } | ||
1948 | 615 | |||
1949 | 762 | gboolean | 616 | gboolean |
1950 | 763 | ubuntu_app_launch_observer_delete_app_paused (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | 617 | ubuntu_app_launch_observer_delete_app_paused (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) |
1951 | 764 | { | 618 | { |
1953 | 765 | return paused_resumed_delete(observer, user_data, &paused_array); | 619 | return observer_delete<UbuntuAppLaunchAppPausedResumedObserver>(observer, user_data, appPausedObservers); |
1954 | 620 | } | ||
1955 | 621 | |||
1956 | 622 | static std::map<std::pair<UbuntuAppLaunchAppPausedResumedObserver, gpointer>, core::ScopedConnection> appResumedObservers; | ||
1957 | 623 | |||
1958 | 624 | gboolean | ||
1959 | 625 | ubuntu_app_launch_observer_add_app_resumed (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | ||
1960 | 626 | { | ||
1961 | 627 | return observer_add_pause<&ubuntu::app_launch::Registry::appResumed>(observer, user_data, appResumedObservers); | ||
1962 | 766 | } | 628 | } |
1963 | 767 | 629 | ||
1964 | 768 | gboolean | 630 | gboolean |
1965 | 769 | ubuntu_app_launch_observer_delete_app_resumed (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | 631 | ubuntu_app_launch_observer_delete_app_resumed (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) |
1966 | 770 | { | 632 | { |
1968 | 771 | return paused_resumed_delete(observer, user_data, &resumed_array); | 633 | return observer_delete<UbuntuAppLaunchAppPausedResumedObserver>(observer, user_data, appResumedObservers); |
1969 | 772 | } | 634 | } |
1970 | 773 | 635 | ||
1971 | 774 | typedef void (*per_instance_func_t) (GDBusConnection * con, GVariant * prop_dict, gpointer user_data); | 636 | typedef void (*per_instance_func_t) (GDBusConnection * con, GVariant * prop_dict, gpointer user_data); |
1972 | 775 | 637 | ||
1973 | === modified file 'tests/CMakeLists.txt' | |||
1974 | --- tests/CMakeLists.txt 2016-09-14 16:43:36 +0000 | |||
1975 | +++ tests/CMakeLists.txt 2017-01-24 04:21:42 +0000 | |||
1976 | @@ -157,6 +157,7 @@ | |||
1977 | 157 | 157 | ||
1978 | 158 | add_custom_target(format-tests | 158 | add_custom_target(format-tests |
1979 | 159 | COMMAND clang-format -i -style=file | 159 | COMMAND clang-format -i -style=file |
1980 | 160 | failure-test.cc | ||
1981 | 160 | application-info-desktop.cpp | 161 | application-info-desktop.cpp |
1982 | 161 | libual-cpp-test.cc | 162 | libual-cpp-test.cc |
1983 | 162 | list-apps.cpp | 163 | list-apps.cpp |
1984 | 163 | 164 | ||
1985 | === modified file 'tests/failure-test.cc' | |||
1986 | --- tests/failure-test.cc 2016-08-25 18:13:44 +0000 | |||
1987 | +++ tests/failure-test.cc 2017-01-24 04:21:42 +0000 | |||
1988 | @@ -17,120 +17,147 @@ | |||
1989 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
1990 | 18 | */ | 18 | */ |
1991 | 19 | 19 | ||
1992 | 20 | #include "eventually-fixture.h" | ||
1993 | 21 | #include "registry.h" | ||
1994 | 22 | #include <gio/gio.h> | ||
1995 | 23 | #include <glib/gstdio.h> | ||
1996 | 20 | #include <gtest/gtest.h> | 24 | #include <gtest/gtest.h> |
1997 | 21 | #include <glib/gstdio.h> | ||
1998 | 22 | #include <gio/gio.h> | ||
1999 | 23 | #include <ubuntu-app-launch.h> | ||
2000 | 24 | #include "eventually-fixture.h" | ||
2001 | 25 | 25 | ||
2002 | 26 | class FailureTest : public EventuallyFixture | 26 | class FailureTest : public EventuallyFixture |
2003 | 27 | { | 27 | { |
2017 | 28 | private: | 28 | private: |
2018 | 29 | GTestDBus * testbus = NULL; | 29 | GTestDBus* testbus = NULL; |
2019 | 30 | 30 | ||
2020 | 31 | protected: | 31 | protected: |
2021 | 32 | virtual void SetUp() { | 32 | std::shared_ptr<ubuntu::app_launch::Registry> registry; |
2022 | 33 | testbus = g_test_dbus_new(G_TEST_DBUS_NONE); | 33 | |
2023 | 34 | g_test_dbus_up(testbus); | 34 | virtual void SetUp() override |
2024 | 35 | } | 35 | { |
2025 | 36 | 36 | /* Click DB test mode */ | |
2026 | 37 | virtual void TearDown() { | 37 | g_setenv("TEST_CLICK_DB", "click-db-dir", TRUE); |
2027 | 38 | g_test_dbus_down(testbus); | 38 | g_setenv("TEST_CLICK_USER", "test-user", TRUE); |
2028 | 39 | g_clear_object(&testbus); | 39 | |
2029 | 40 | } | 40 | gchar* linkfarmpath = g_build_filename(CMAKE_SOURCE_DIR, "link-farm", NULL); |
2030 | 41 | g_setenv("UBUNTU_APP_LAUNCH_LINK_FARM", linkfarmpath, TRUE); | ||
2031 | 42 | g_free(linkfarmpath); | ||
2032 | 43 | |||
2033 | 44 | g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE); | ||
2034 | 45 | g_setenv("XDG_CACHE_HOME", CMAKE_SOURCE_DIR "/libertine-data", TRUE); | ||
2035 | 46 | g_setenv("XDG_DATA_HOME", CMAKE_SOURCE_DIR "/libertine-home", TRUE); | ||
2036 | 47 | |||
2037 | 48 | testbus = g_test_dbus_new(G_TEST_DBUS_NONE); | ||
2038 | 49 | g_test_dbus_up(testbus); | ||
2039 | 50 | |||
2040 | 51 | registry = std::make_shared<ubuntu::app_launch::Registry>(); | ||
2041 | 52 | } | ||
2042 | 53 | |||
2043 | 54 | virtual void TearDown() override | ||
2044 | 55 | { | ||
2045 | 56 | registry.reset(); | ||
2046 | 57 | |||
2047 | 58 | g_test_dbus_down(testbus); | ||
2048 | 59 | g_clear_object(&testbus); | ||
2049 | 60 | } | ||
2050 | 41 | }; | 61 | }; |
2051 | 42 | 62 | ||
2052 | 43 | static void | ||
2053 | 44 | failed_observer (const gchar * appid, UbuntuAppLaunchAppFailed reason, gpointer user_data) | ||
2054 | 45 | { | ||
2055 | 46 | if (reason == UBUNTU_APP_LAUNCH_APP_FAILED_CRASH) { | ||
2056 | 47 | std::string * last = static_cast<std::string *>(user_data); | ||
2057 | 48 | *last = appid; | ||
2058 | 49 | } | ||
2059 | 50 | } | ||
2060 | 51 | |||
2061 | 52 | TEST_F(FailureTest, CrashTest) | 63 | TEST_F(FailureTest, CrashTest) |
2062 | 53 | { | 64 | { |
2085 | 54 | g_setenv("EXIT_STATUS", "-100", TRUE); | 65 | g_setenv("EXIT_STATUS", "-100", TRUE); |
2086 | 55 | g_setenv("JOB", "application-click", TRUE); | 66 | g_setenv("JOB", "application-click", TRUE); |
2087 | 56 | g_setenv("INSTANCE", "foo", TRUE); | 67 | g_setenv("INSTANCE", "foo", TRUE); |
2088 | 57 | 68 | ||
2089 | 58 | std::string last_observer; | 69 | std::string last_observer; |
2090 | 59 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_failed(failed_observer, &last_observer)); | 70 | ubuntu::app_launch::Registry::appFailed(registry).connect( |
2091 | 60 | 71 | [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, | |
2092 | 61 | /* Status based */ | 72 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
2093 | 62 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | 73 | ubuntu::app_launch::Registry::FailureType type) { |
2094 | 63 | 74 | if (type == ubuntu::app_launch::Registry::FailureType::CRASH) | |
2095 | 64 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | 75 | { |
2096 | 65 | 76 | last_observer = app->appId(); | |
2097 | 66 | last_observer.clear(); | 77 | } |
2098 | 67 | g_unsetenv("EXIT_STATUS"); | 78 | }); |
2099 | 68 | g_setenv("EXIT_SIGNAL", "KILL", TRUE); | 79 | |
2100 | 69 | 80 | /* Status based */ | |
2101 | 70 | /* Signal based */ | 81 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
2102 | 71 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | 82 | |
2103 | 72 | 83 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | |
2104 | 73 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | 84 | |
2105 | 74 | 85 | last_observer.clear(); | |
2106 | 75 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_failed(failed_observer, &last_observer)); | 86 | g_unsetenv("EXIT_STATUS"); |
2107 | 87 | g_setenv("EXIT_SIGNAL", "KILL", TRUE); | ||
2108 | 88 | |||
2109 | 89 | /* Signal based */ | ||
2110 | 90 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | ||
2111 | 91 | |||
2112 | 92 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | ||
2113 | 76 | } | 93 | } |
2114 | 77 | 94 | ||
2115 | 78 | TEST_F(FailureTest, LegacyTest) | 95 | TEST_F(FailureTest, LegacyTest) |
2116 | 79 | { | 96 | { |
2130 | 80 | g_setenv("EXIT_STATUS", "-100", TRUE); | 97 | g_setenv("EXIT_STATUS", "-100", TRUE); |
2131 | 81 | g_setenv("JOB", "application-legacy", TRUE); | 98 | g_setenv("JOB", "application-legacy", TRUE); |
2132 | 82 | g_setenv("INSTANCE", "foo-1234", TRUE); | 99 | g_setenv("INSTANCE", "foo-1234", TRUE); |
2133 | 83 | 100 | ||
2134 | 84 | std::string last_observer; | 101 | std::string last_observer; |
2135 | 85 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_failed(failed_observer, &last_observer)); | 102 | ubuntu::app_launch::Registry::appFailed(registry).connect( |
2136 | 86 | 103 | [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, | |
2137 | 87 | /* Status based */ | 104 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
2138 | 88 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | 105 | ubuntu::app_launch::Registry::FailureType type) { |
2139 | 89 | 106 | g_debug("Signal handler called"); | |
2140 | 90 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | 107 | if (type == ubuntu::app_launch::Registry::FailureType::CRASH) |
2141 | 91 | 108 | { | |
2142 | 92 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_failed(failed_observer, &last_observer)); | 109 | last_observer = app->appId(); |
2143 | 110 | } | ||
2144 | 111 | }); | ||
2145 | 112 | |||
2146 | 113 | /* Status based */ | ||
2147 | 114 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | ||
2148 | 115 | |||
2149 | 116 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | ||
2150 | 93 | } | 117 | } |
2151 | 94 | 118 | ||
2152 | 95 | TEST_F(FailureTest, SnapTest) | 119 | TEST_F(FailureTest, SnapTest) |
2153 | 96 | { | 120 | { |
2176 | 97 | g_setenv("EXIT_STATUS", "-100", TRUE); | 121 | g_setenv("EXIT_STATUS", "-100", TRUE); |
2177 | 98 | g_setenv("JOB", "application-snap", TRUE); | 122 | g_setenv("JOB", "application-snap", TRUE); |
2178 | 99 | g_setenv("INSTANCE", "foo_bar_x123-1234", TRUE); | 123 | g_setenv("INSTANCE", "com.test.good_application_1.2.3-1234", TRUE); |
2179 | 100 | 124 | ||
2180 | 101 | std::string last_observer; | 125 | std::string last_observer; |
2181 | 102 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_failed(failed_observer, &last_observer)); | 126 | ubuntu::app_launch::Registry::appFailed(registry).connect( |
2182 | 103 | 127 | [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, | |
2183 | 104 | /* Status based */ | 128 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
2184 | 105 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | 129 | ubuntu::app_launch::Registry::FailureType type) { |
2185 | 106 | 130 | if (type == ubuntu::app_launch::Registry::FailureType::CRASH) | |
2186 | 107 | EXPECT_EVENTUALLY_EQ("foo_bar_x123", last_observer); | 131 | { |
2187 | 108 | 132 | last_observer = app->appId(); | |
2188 | 109 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_failed(failed_observer, &last_observer)); | 133 | } |
2189 | 110 | } | 134 | }); |
2190 | 111 | 135 | ||
2191 | 112 | static void | 136 | /* Status based */ |
2192 | 113 | failed_start_observer (const gchar * appid, UbuntuAppLaunchAppFailed reason, gpointer user_data) | 137 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
2193 | 114 | { | 138 | |
2194 | 115 | if (reason == UBUNTU_APP_LAUNCH_APP_FAILED_START_FAILURE) { | 139 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", last_observer); |
2173 | 116 | std::string * last = static_cast<std::string *>(user_data); | ||
2174 | 117 | *last = appid; | ||
2175 | 118 | } | ||
2195 | 119 | } | 140 | } |
2196 | 120 | 141 | ||
2197 | 121 | TEST_F(FailureTest, StartTest) | 142 | TEST_F(FailureTest, StartTest) |
2198 | 122 | { | 143 | { |
2212 | 123 | g_setenv("JOB", "application-click", TRUE); | 144 | g_setenv("JOB", "application-click", TRUE); |
2213 | 124 | g_setenv("INSTANCE", "foo", TRUE); | 145 | g_setenv("INSTANCE", "foo", TRUE); |
2214 | 125 | g_unsetenv("EXIT_STATUS"); | 146 | g_unsetenv("EXIT_STATUS"); |
2215 | 126 | g_unsetenv("EXIT_SIGNAL"); | 147 | g_unsetenv("EXIT_SIGNAL"); |
2216 | 127 | 148 | ||
2217 | 128 | std::string last_observer; | 149 | std::string last_observer; |
2218 | 129 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_failed(failed_start_observer, &last_observer)); | 150 | ubuntu::app_launch::Registry::appFailed(registry).connect( |
2219 | 130 | 151 | [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, | |
2220 | 131 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | 152 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
2221 | 132 | 153 | ubuntu::app_launch::Registry::FailureType type) { | |
2222 | 133 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | 154 | if (type == ubuntu::app_launch::Registry::FailureType::START_FAILURE) |
2223 | 134 | 155 | { | |
2224 | 135 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_failed(failed_start_observer, &last_observer)); | 156 | last_observer = app->appId(); |
2225 | 157 | } | ||
2226 | 158 | }); | ||
2227 | 159 | |||
2228 | 160 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | ||
2229 | 161 | |||
2230 | 162 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | ||
2231 | 136 | } | 163 | } |
2232 | 137 | 164 | ||
2233 | === modified file 'tests/libual-cpp-test.cc' | |||
2234 | --- tests/libual-cpp-test.cc 2017-01-10 18:41:25 +0000 | |||
2235 | +++ tests/libual-cpp-test.cc 2017-01-24 04:21:42 +0000 | |||
2236 | @@ -49,32 +49,73 @@ | |||
2237 | 49 | DbusTestDbusMock* mock = NULL; | 49 | DbusTestDbusMock* mock = NULL; |
2238 | 50 | DbusTestDbusMock* cgmock = NULL; | 50 | DbusTestDbusMock* cgmock = NULL; |
2239 | 51 | GDBusConnection* bus = NULL; | 51 | GDBusConnection* bus = NULL; |
2240 | 52 | std::string last_focus_appid; | ||
2241 | 53 | std::string last_resume_appid; | ||
2242 | 54 | guint resume_timeout = 0; | 52 | guint resume_timeout = 0; |
2243 | 55 | std::shared_ptr<ubuntu::app_launch::Registry> registry; | 53 | std::shared_ptr<ubuntu::app_launch::Registry> registry; |
2244 | 56 | 54 | ||
2266 | 57 | private: | 55 | class ManagerMock : public ubuntu::app_launch::Registry::Manager |
2267 | 58 | static void focus_cb(const gchar* appid, gpointer user_data) | 56 | { |
2268 | 59 | { | 57 | GLib::ContextThread thread; |
2269 | 60 | g_debug("Focus Callback: %s", appid); | 58 | |
2270 | 61 | LibUAL* _this = static_cast<LibUAL*>(user_data); | 59 | public: |
2271 | 62 | _this->last_focus_appid = appid; | 60 | ManagerMock() |
2272 | 63 | } | 61 | { |
2273 | 64 | 62 | g_debug("Building a Manager Mock"); | |
2274 | 65 | static void resume_cb(const gchar* appid, gpointer user_data) | 63 | } |
2275 | 66 | { | 64 | |
2276 | 67 | g_debug("Resume Callback: %s", appid); | 65 | ~ManagerMock() |
2277 | 68 | LibUAL* _this = static_cast<LibUAL*>(user_data); | 66 | { |
2278 | 69 | _this->last_resume_appid = appid; | 67 | g_debug("Freeing a Manager Mock"); |
2279 | 70 | 68 | } | |
2280 | 71 | if (_this->resume_timeout > 0) | 69 | |
2281 | 72 | { | 70 | void quit() |
2282 | 73 | _this->pause(_this->resume_timeout); | 71 | { |
2283 | 74 | } | 72 | thread.quit(); |
2284 | 75 | } | 73 | } |
2285 | 76 | 74 | ||
2286 | 77 | protected: | 75 | ubuntu::app_launch::AppID lastStartedApp; |
2287 | 76 | ubuntu::app_launch::AppID lastFocusedApp; | ||
2288 | 77 | ubuntu::app_launch::AppID lastResumedApp; | ||
2289 | 78 | |||
2290 | 79 | bool startingResponse{true}; | ||
2291 | 80 | bool focusResponse{true}; | ||
2292 | 81 | bool resumeResponse{true}; | ||
2293 | 82 | |||
2294 | 83 | std::chrono::milliseconds startingTimeout{0}; | ||
2295 | 84 | std::chrono::milliseconds focusTimeout{0}; | ||
2296 | 85 | std::chrono::milliseconds resumeTimeout{0}; | ||
2297 | 86 | |||
2298 | 87 | void startingRequest(const std::shared_ptr<ubuntu::app_launch::Application>& app, | ||
2299 | 88 | const std::shared_ptr<ubuntu::app_launch::Application::Instance>& instance, | ||
2300 | 89 | std::function<void(bool)> reply) override | ||
2301 | 90 | { | ||
2302 | 91 | thread.timeout(startingTimeout, [this, app, instance, reply]() { | ||
2303 | 92 | lastStartedApp = app->appId(); | ||
2304 | 93 | reply(startingResponse); | ||
2305 | 94 | }); | ||
2306 | 95 | } | ||
2307 | 96 | |||
2308 | 97 | void focusRequest(const std::shared_ptr<ubuntu::app_launch::Application>& app, | ||
2309 | 98 | const std::shared_ptr<ubuntu::app_launch::Application::Instance>& instance, | ||
2310 | 99 | std::function<void(bool)> reply) override | ||
2311 | 100 | { | ||
2312 | 101 | thread.timeout(focusTimeout, [this, app, instance, reply]() { | ||
2313 | 102 | lastFocusedApp = app->appId(); | ||
2314 | 103 | reply(focusResponse); | ||
2315 | 104 | }); | ||
2316 | 105 | } | ||
2317 | 106 | |||
2318 | 107 | void resumeRequest(const std::shared_ptr<ubuntu::app_launch::Application>& app, | ||
2319 | 108 | const std::shared_ptr<ubuntu::app_launch::Application::Instance>& instance, | ||
2320 | 109 | std::function<void(bool)> reply) override | ||
2321 | 110 | { | ||
2322 | 111 | thread.timeout(resumeTimeout, [this, app, instance, reply]() { | ||
2323 | 112 | lastResumedApp = app->appId(); | ||
2324 | 113 | reply(resumeResponse); | ||
2325 | 114 | }); | ||
2326 | 115 | } | ||
2327 | 116 | }; | ||
2328 | 117 | std::shared_ptr<ManagerMock> manager; | ||
2329 | 118 | |||
2330 | 78 | /* Useful debugging stuff, but not on by default. You really want to | 119 | /* Useful debugging stuff, but not on by default. You really want to |
2331 | 79 | not get all this noise typically */ | 120 | not get all this noise typically */ |
2332 | 80 | void debugConnection() | 121 | void debugConnection() |
2333 | @@ -127,13 +168,13 @@ | |||
2334 | 127 | 168 | ||
2335 | 128 | dbus_test_dbus_mock_object_add_method(mock, obj, "GetJobByName", G_VARIANT_TYPE("s"), G_VARIANT_TYPE("o"), | 169 | dbus_test_dbus_mock_object_add_method(mock, obj, "GetJobByName", G_VARIANT_TYPE("s"), G_VARIANT_TYPE("o"), |
2336 | 129 | "if args[0] == 'application-click':\n" | 170 | "if args[0] == 'application-click':\n" |
2338 | 130 | " ret = dbus.ObjectPath('/com/test/application_click')\n" | 171 | " ret = dbus.ObjectPath('/com/test/application_click')\n" |
2339 | 131 | "elif args[0] == 'application-snap':\n" | 172 | "elif args[0] == 'application-snap':\n" |
2341 | 132 | " ret = dbus.ObjectPath('/com/test/application_snap')\n" | 173 | " ret = dbus.ObjectPath('/com/test/application_snap')\n" |
2342 | 133 | "elif args[0] == 'application-legacy':\n" | 174 | "elif args[0] == 'application-legacy':\n" |
2344 | 134 | " ret = dbus.ObjectPath('/com/test/application_legacy')\n" | 175 | " ret = dbus.ObjectPath('/com/test/application_legacy')\n" |
2345 | 135 | "elif args[0] == 'untrusted-helper':\n" | 176 | "elif args[0] == 'untrusted-helper':\n" |
2347 | 136 | " ret = dbus.ObjectPath('/com/test/untrusted/helper')\n", | 177 | " ret = dbus.ObjectPath('/com/test/untrusted/helper')\n", |
2348 | 137 | NULL); | 178 | NULL); |
2349 | 138 | 179 | ||
2350 | 139 | dbus_test_dbus_mock_object_add_method(mock, obj, "SetEnv", G_VARIANT_TYPE("(assb)"), NULL, "", NULL); | 180 | dbus_test_dbus_mock_object_add_method(mock, obj, "SetEnv", G_VARIANT_TYPE("(assb)"), NULL, "", NULL); |
2351 | @@ -272,18 +313,23 @@ | |||
2352 | 272 | /* Make sure we pretend the CG manager is just on our bus */ | 313 | /* Make sure we pretend the CG manager is just on our bus */ |
2353 | 273 | g_setenv("UBUNTU_APP_LAUNCH_CG_MANAGER_SESSION_BUS", "YES", TRUE); | 314 | g_setenv("UBUNTU_APP_LAUNCH_CG_MANAGER_SESSION_BUS", "YES", TRUE); |
2354 | 274 | 315 | ||
2355 | 275 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_focus(focus_cb, this)); | ||
2356 | 276 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_resume(resume_cb, this)); | ||
2357 | 277 | |||
2358 | 278 | registry = std::make_shared<ubuntu::app_launch::Registry>(); | 316 | registry = std::make_shared<ubuntu::app_launch::Registry>(); |
2359 | 317 | |||
2360 | 318 | manager = std::make_shared<ManagerMock>(); | ||
2361 | 319 | ubuntu::app_launch::Registry::setManager(manager, registry); | ||
2362 | 279 | } | 320 | } |
2363 | 280 | 321 | ||
2364 | 281 | virtual void TearDown() | 322 | virtual void TearDown() |
2365 | 282 | { | 323 | { |
2369 | 283 | ubuntu_app_launch_observer_delete_app_focus(focus_cb, this); | 324 | manager->quit(); |
2367 | 284 | ubuntu_app_launch_observer_delete_app_resume(resume_cb, this); | ||
2368 | 285 | |||
2370 | 286 | registry.reset(); | 325 | registry.reset(); |
2371 | 326 | manager.reset(); | ||
2372 | 327 | |||
2373 | 328 | // NOTE: This should generally always be commented out, but | ||
2374 | 329 | // it is useful for debugging common errors, so leaving it | ||
2375 | 330 | // as a comment to make debugging those eaiser. | ||
2376 | 331 | // | ||
2377 | 332 | // ubuntu::app_launch::Registry::clearDefault(); | ||
2378 | 287 | 333 | ||
2379 | 288 | g_clear_object(&mock); | 334 | g_clear_object(&mock); |
2380 | 289 | g_clear_object(&cgmock); | 335 | g_clear_object(&cgmock); |
2381 | @@ -832,33 +878,30 @@ | |||
2382 | 832 | #endif | 878 | #endif |
2383 | 833 | } | 879 | } |
2384 | 834 | 880 | ||
2385 | 835 | typedef struct | ||
2386 | 836 | { | ||
2387 | 837 | unsigned int count; | ||
2388 | 838 | const gchar* name; | ||
2389 | 839 | } observer_data_t; | ||
2390 | 840 | |||
2391 | 841 | static void observer_cb(const gchar* appid, gpointer user_data) | ||
2392 | 842 | { | ||
2393 | 843 | observer_data_t* data = (observer_data_t*)user_data; | ||
2394 | 844 | |||
2395 | 845 | if (data->name == NULL) | ||
2396 | 846 | { | ||
2397 | 847 | data->count++; | ||
2398 | 848 | } | ||
2399 | 849 | else if (g_strcmp0(data->name, appid) == 0) | ||
2400 | 850 | { | ||
2401 | 851 | data->count++; | ||
2402 | 852 | } | ||
2403 | 853 | } | ||
2404 | 854 | |||
2405 | 855 | TEST_F(LibUAL, StartStopObserver) | 881 | TEST_F(LibUAL, StartStopObserver) |
2406 | 856 | { | 882 | { |
2412 | 857 | observer_data_t start_data = {.count = 0, .name = nullptr}; | 883 | int start_count = 0; |
2413 | 858 | observer_data_t stop_data = {.count = 0, .name = nullptr}; | 884 | int stop_count = 0; |
2414 | 859 | 885 | ubuntu::app_launch::AppID start_appid; | |
2415 | 860 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_started(observer_cb, &start_data)); | 886 | ubuntu::app_launch::AppID stop_appid; |
2416 | 861 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_stop(observer_cb, &stop_data)); | 887 | |
2417 | 888 | ubuntu::app_launch::Registry::appStarted(registry).connect( | ||
2418 | 889 | [&start_count, &start_appid](std::shared_ptr<ubuntu::app_launch::Application> app, | ||
2419 | 890 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { | ||
2420 | 891 | if (!start_appid.empty() && !(start_appid == app->appId())) | ||
2421 | 892 | return; | ||
2422 | 893 | |||
2423 | 894 | start_count++; | ||
2424 | 895 | }); | ||
2425 | 896 | |||
2426 | 897 | ubuntu::app_launch::Registry::appStopped(registry).connect( | ||
2427 | 898 | [&stop_count, &stop_appid](std::shared_ptr<ubuntu::app_launch::Application> app, | ||
2428 | 899 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { | ||
2429 | 900 | if (!stop_appid.empty() && !(stop_appid == app->appId())) | ||
2430 | 901 | return; | ||
2431 | 902 | |||
2432 | 903 | stop_count++; | ||
2433 | 904 | }); | ||
2434 | 862 | 905 | ||
2435 | 863 | DbusTestDbusMockObject* obj = | 906 | DbusTestDbusMockObject* obj = |
2436 | 864 | dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); | 907 | dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); |
2437 | @@ -869,7 +912,7 @@ | |||
2438 | 869 | g_variant_new_parsed("('started', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), | 912 | g_variant_new_parsed("('started', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), |
2439 | 870 | NULL); | 913 | NULL); |
2440 | 871 | 914 | ||
2442 | 872 | EXPECT_EVENTUALLY_EQ(1, start_data.count); | 915 | EXPECT_EVENTUALLY_EQ(1, start_count); |
2443 | 873 | 916 | ||
2444 | 874 | /* Basic stop */ | 917 | /* Basic stop */ |
2445 | 875 | dbus_test_dbus_mock_object_emit_signal( | 918 | dbus_test_dbus_mock_object_emit_signal( |
2446 | @@ -877,33 +920,41 @@ | |||
2447 | 877 | g_variant_new_parsed("('stopped', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), | 920 | g_variant_new_parsed("('stopped', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), |
2448 | 878 | NULL); | 921 | NULL); |
2449 | 879 | 922 | ||
2451 | 880 | EXPECT_EVENTUALLY_EQ(1, stop_data.count); | 923 | EXPECT_EVENTUALLY_EQ(1, stop_count); |
2452 | 881 | 924 | ||
2453 | 882 | /* Start legacy */ | 925 | /* Start legacy */ |
2456 | 883 | start_data.count = 0; | 926 | start_count = 0; |
2457 | 884 | start_data.name = "multiple"; | 927 | start_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw({}), |
2458 | 928 | ubuntu::app_launch::AppID::AppName::from_raw("multiple"), | ||
2459 | 929 | ubuntu::app_launch::AppID::Version::from_raw({})}; | ||
2460 | 885 | 930 | ||
2461 | 886 | dbus_test_dbus_mock_object_emit_signal( | 931 | dbus_test_dbus_mock_object_emit_signal( |
2462 | 887 | mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), | 932 | mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
2463 | 888 | g_variant_new_parsed("('started', ['JOB=application-legacy', 'INSTANCE=multiple-234235'])"), NULL); | 933 | g_variant_new_parsed("('started', ['JOB=application-legacy', 'INSTANCE=multiple-234235'])"), NULL); |
2464 | 889 | 934 | ||
2466 | 890 | EXPECT_EVENTUALLY_EQ(1, start_data.count); | 935 | EXPECT_EVENTUALLY_EQ(1, start_count); |
2467 | 891 | 936 | ||
2468 | 892 | /* Legacy stop */ | 937 | /* Legacy stop */ |
2471 | 893 | stop_data.count = 0; | 938 | stop_count = 0; |
2472 | 894 | stop_data.name = "bar"; | 939 | stop_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw({}), |
2473 | 940 | ubuntu::app_launch::AppID::AppName::from_raw("foo"), | ||
2474 | 941 | ubuntu::app_launch::AppID::Version::from_raw({})}; | ||
2475 | 895 | 942 | ||
2476 | 896 | dbus_test_dbus_mock_object_emit_signal( | 943 | dbus_test_dbus_mock_object_emit_signal( |
2477 | 897 | mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), | 944 | mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
2479 | 898 | g_variant_new_parsed("('stopped', ['JOB=application-legacy', 'INSTANCE=bar-9344321'])"), NULL); | 945 | g_variant_new_parsed("('stopped', ['JOB=application-legacy', 'INSTANCE=foo-9344321'])"), NULL); |
2480 | 899 | 946 | ||
2482 | 900 | EXPECT_EVENTUALLY_EQ(1, stop_data.count); | 947 | EXPECT_EVENTUALLY_EQ(1, stop_count); |
2483 | 901 | 948 | ||
2484 | 902 | /* Test Noise Start */ | 949 | /* Test Noise Start */ |
2489 | 903 | start_data.count = 0; | 950 | start_count = 0; |
2490 | 904 | start_data.name = "com.test.good_application_1.2.3"; | 951 | start_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw("com.test.good"), |
2491 | 905 | stop_data.count = 0; | 952 | ubuntu::app_launch::AppID::AppName::from_raw("application"), |
2492 | 906 | stop_data.name = "com.test.good_application_1.2.3"; | 953 | ubuntu::app_launch::AppID::Version::from_raw("1.2.3")}; |
2493 | 954 | stop_count = 0; | ||
2494 | 955 | stop_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw("com.test.good"), | ||
2495 | 956 | ubuntu::app_launch::AppID::AppName::from_raw("application"), | ||
2496 | 957 | ubuntu::app_launch::AppID::Version::from_raw("1.2.3")}; | ||
2497 | 907 | 958 | ||
2498 | 908 | /* A full lifecycle */ | 959 | /* A full lifecycle */ |
2499 | 909 | dbus_test_dbus_mock_object_emit_signal( | 960 | dbus_test_dbus_mock_object_emit_signal( |
2500 | @@ -924,46 +975,33 @@ | |||
2501 | 924 | NULL); | 975 | NULL); |
2502 | 925 | 976 | ||
2503 | 926 | /* Ensure we just signaled once for each */ | 977 | /* Ensure we just signaled once for each */ |
2533 | 927 | EXPECT_EVENTUALLY_EQ(1, start_data.count); | 978 | EXPECT_EVENTUALLY_EQ(1, start_count); |
2534 | 928 | EXPECT_EVENTUALLY_EQ(1, stop_data.count); | 979 | EXPECT_EVENTUALLY_EQ(1, stop_count); |
2506 | 929 | |||
2507 | 930 | /* Remove */ | ||
2508 | 931 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_started(observer_cb, &start_data)); | ||
2509 | 932 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_stop(observer_cb, &stop_data)); | ||
2510 | 933 | } | ||
2511 | 934 | |||
2512 | 935 | static GDBusMessage* filter_starting(GDBusConnection* conn, | ||
2513 | 936 | GDBusMessage* message, | ||
2514 | 937 | gboolean incomming, | ||
2515 | 938 | gpointer user_data) | ||
2516 | 939 | { | ||
2517 | 940 | if (g_strcmp0(g_dbus_message_get_member(message), "UnityStartingSignal") == 0) | ||
2518 | 941 | { | ||
2519 | 942 | unsigned int* count = static_cast<unsigned int*>(user_data); | ||
2520 | 943 | (*count)++; | ||
2521 | 944 | g_object_unref(message); | ||
2522 | 945 | return NULL; | ||
2523 | 946 | } | ||
2524 | 947 | |||
2525 | 948 | return message; | ||
2526 | 949 | } | ||
2527 | 950 | |||
2528 | 951 | static void starting_observer(const gchar* appid, gpointer user_data) | ||
2529 | 952 | { | ||
2530 | 953 | std::string* last = static_cast<std::string*>(user_data); | ||
2531 | 954 | *last = appid; | ||
2532 | 955 | return; | ||
2535 | 956 | } | 980 | } |
2536 | 957 | 981 | ||
2537 | 958 | TEST_F(LibUAL, StartingResponses) | 982 | TEST_F(LibUAL, StartingResponses) |
2538 | 959 | { | 983 | { |
2540 | 960 | std::string last_observer; | 984 | /* Get Bus */ |
2541 | 985 | GDBusConnection* session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | ||
2542 | 986 | |||
2543 | 987 | /* Setup filter to count signals out */ | ||
2544 | 961 | unsigned int starting_count = 0; | 988 | unsigned int starting_count = 0; |
2550 | 962 | GDBusConnection* session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | 989 | guint filter = g_dbus_connection_add_filter( |
2551 | 963 | guint filter = g_dbus_connection_add_filter(session, filter_starting, &starting_count, NULL); | 990 | session, |
2552 | 964 | 991 | [](GDBusConnection* conn, GDBusMessage* message, gboolean incomming, gpointer user_data) -> GDBusMessage* { | |
2553 | 965 | EXPECT_TRUE(ubuntu_app_launch_observer_add_app_starting(starting_observer, &last_observer)); | 992 | if (g_strcmp0(g_dbus_message_get_member(message), "UnityStartingSignal") == 0) |
2554 | 966 | 993 | { | |
2555 | 994 | unsigned int* count = static_cast<unsigned int*>(user_data); | ||
2556 | 995 | (*count)++; | ||
2557 | 996 | g_object_unref(message); | ||
2558 | 997 | return NULL; | ||
2559 | 998 | } | ||
2560 | 999 | |||
2561 | 1000 | return message; | ||
2562 | 1001 | }, | ||
2563 | 1002 | &starting_count, NULL); | ||
2564 | 1003 | |||
2565 | 1004 | /* Emit a signal */ | ||
2566 | 967 | g_dbus_connection_emit_signal(session, NULL, /* destination */ | 1005 | g_dbus_connection_emit_signal(session, NULL, /* destination */ |
2567 | 968 | "/", /* path */ | 1006 | "/", /* path */ |
2568 | 969 | "com.canonical.UbuntuAppLaunch", /* interface */ | 1007 | "com.canonical.UbuntuAppLaunch", /* interface */ |
2569 | @@ -971,11 +1009,15 @@ | |||
2570 | 971 | g_variant_new("(s)", "com.test.good_application_1.2.3"), /* params, the same */ | 1009 | g_variant_new("(s)", "com.test.good_application_1.2.3"), /* params, the same */ |
2571 | 972 | NULL); | 1010 | NULL); |
2572 | 973 | 1011 | ||
2574 | 974 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", last_observer); | 1012 | /* Make sure we run our observer */ |
2575 | 1013 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID(ubuntu::app_launch::AppID::Package::from_raw("com.test.good"), | ||
2576 | 1014 | ubuntu::app_launch::AppID::AppName::from_raw("application"), | ||
2577 | 1015 | ubuntu::app_launch::AppID::Version::from_raw("1.2.3")), | ||
2578 | 1016 | manager->lastStartedApp); | ||
2579 | 1017 | |||
2580 | 1018 | /* Make sure we return */ | ||
2581 | 975 | EXPECT_EVENTUALLY_EQ(1, starting_count); | 1019 | EXPECT_EVENTUALLY_EQ(1, starting_count); |
2582 | 976 | 1020 | ||
2583 | 977 | EXPECT_TRUE(ubuntu_app_launch_observer_delete_app_starting(starting_observer, &last_observer)); | ||
2584 | 978 | |||
2585 | 979 | g_dbus_connection_remove_filter(session, filter); | 1021 | g_dbus_connection_remove_filter(session, filter); |
2586 | 980 | g_object_unref(session); | 1022 | g_object_unref(session); |
2587 | 981 | } | 1023 | } |
2588 | @@ -986,8 +1028,10 @@ | |||
2589 | 986 | auto app = ubuntu::app_launch::Application::create(appid, registry); | 1028 | auto app = ubuntu::app_launch::Application::create(appid, registry); |
2590 | 987 | app->launch(); | 1029 | app->launch(); |
2591 | 988 | 1030 | ||
2594 | 989 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 1031 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2595 | 990 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 1032 | this->manager->lastFocusedApp); |
2596 | 1033 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2597 | 1034 | this->manager->lastResumedApp); | ||
2598 | 991 | } | 1035 | } |
2599 | 992 | 1036 | ||
2600 | 993 | GDBusMessage* filter_func_good(GDBusConnection* conn, GDBusMessage* message, gboolean incomming, gpointer user_data) | 1037 | GDBusMessage* filter_func_good(GDBusConnection* conn, GDBusMessage* message, gboolean incomming, gpointer user_data) |
2601 | @@ -1021,8 +1065,10 @@ | |||
2602 | 1021 | 1065 | ||
2603 | 1022 | app->launch(uris); | 1066 | app->launch(uris); |
2604 | 1023 | 1067 | ||
2607 | 1024 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 1068 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2608 | 1025 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 1069 | this->manager->lastFocusedApp); |
2609 | 1070 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2610 | 1071 | this->manager->lastResumedApp); | ||
2611 | 1026 | 1072 | ||
2612 | 1027 | g_dbus_connection_remove_filter(session, filter); | 1073 | g_dbus_connection_remove_filter(session, filter); |
2613 | 1028 | 1074 | ||
2614 | @@ -1054,8 +1100,10 @@ | |||
2615 | 1054 | 1100 | ||
2616 | 1055 | app->launch(uris); | 1101 | app->launch(uris); |
2617 | 1056 | 1102 | ||
2620 | 1057 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 1103 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2621 | 1058 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 1104 | this->manager->lastFocusedApp); |
2622 | 1105 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2623 | 1106 | this->manager->lastResumedApp); | ||
2624 | 1059 | } | 1107 | } |
2625 | 1060 | 1108 | ||
2626 | 1061 | TEST_F(LibUAL, UnityTimeoutTest) | 1109 | TEST_F(LibUAL, UnityTimeoutTest) |
2627 | @@ -1067,8 +1115,10 @@ | |||
2628 | 1067 | 1115 | ||
2629 | 1068 | app->launch(); | 1116 | app->launch(); |
2630 | 1069 | 1117 | ||
2633 | 1070 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 1118 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2634 | 1071 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 1119 | this->manager->lastResumedApp); |
2635 | 1120 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2636 | 1121 | this->manager->lastFocusedApp); | ||
2637 | 1072 | } | 1122 | } |
2638 | 1073 | 1123 | ||
2639 | 1074 | TEST_F(LibUAL, UnityTimeoutUriTest) | 1124 | TEST_F(LibUAL, UnityTimeoutUriTest) |
2640 | @@ -1082,8 +1132,10 @@ | |||
2641 | 1082 | 1132 | ||
2642 | 1083 | app->launch(uris); | 1133 | app->launch(uris); |
2643 | 1084 | 1134 | ||
2646 | 1085 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 1135 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2647 | 1086 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 1136 | this->manager->lastFocusedApp); |
2648 | 1137 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2649 | 1138 | this->manager->lastResumedApp); | ||
2650 | 1087 | } | 1139 | } |
2651 | 1088 | 1140 | ||
2652 | 1089 | GDBusMessage* filter_respawn(GDBusConnection* conn, GDBusMessage* message, gboolean incomming, gpointer user_data) | 1141 | GDBusMessage* filter_respawn(GDBusConnection* conn, GDBusMessage* message, gboolean incomming, gpointer user_data) |
2653 | @@ -1116,8 +1168,10 @@ | |||
2654 | 1116 | g_debug("Start call time: %d ms", (end - start) / 1000); | 1168 | g_debug("Start call time: %d ms", (end - start) / 1000); |
2655 | 1117 | EXPECT_LT(end - start, 2000 * 1000); | 1169 | EXPECT_LT(end - start, 2000 * 1000); |
2656 | 1118 | 1170 | ||
2659 | 1119 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 1171 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2660 | 1120 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 1172 | this->manager->lastFocusedApp); |
2661 | 1173 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2662 | 1174 | this->manager->lastResumedApp); | ||
2663 | 1121 | 1175 | ||
2664 | 1122 | g_dbus_connection_remove_filter(session, filter); | 1176 | g_dbus_connection_remove_filter(session, filter); |
2665 | 1123 | g_object_unref(session); | 1177 | g_object_unref(session); |
2666 | @@ -1177,23 +1231,21 @@ | |||
2667 | 1177 | g_variant_unref(env); | 1231 | g_variant_unref(env); |
2668 | 1178 | } | 1232 | } |
2669 | 1179 | 1233 | ||
2670 | 1180 | static void failed_observer(const gchar* appid, UbuntuAppLaunchAppFailed reason, gpointer user_data) | ||
2671 | 1181 | { | ||
2672 | 1182 | if (reason == UBUNTU_APP_LAUNCH_APP_FAILED_CRASH) | ||
2673 | 1183 | { | ||
2674 | 1184 | std::string* last = static_cast<std::string*>(user_data); | ||
2675 | 1185 | *last = appid; | ||
2676 | 1186 | } | ||
2677 | 1187 | return; | ||
2678 | 1188 | } | ||
2679 | 1189 | |||
2680 | 1190 | TEST_F(LibUAL, FailingObserver) | 1234 | TEST_F(LibUAL, FailingObserver) |
2681 | 1191 | { | 1235 | { |
2683 | 1192 | std::string last_observer; | 1236 | ubuntu::app_launch::AppID lastFailedApp; |
2684 | 1237 | ubuntu::app_launch::Registry::FailureType lastFailedType; | ||
2685 | 1238 | |||
2686 | 1239 | ubuntu::app_launch::Registry::appFailed(registry).connect( | ||
2687 | 1240 | [&lastFailedApp, &lastFailedType](std::shared_ptr<ubuntu::app_launch::Application> app, | ||
2688 | 1241 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, | ||
2689 | 1242 | ubuntu::app_launch::Registry::FailureType type) { | ||
2690 | 1243 | lastFailedApp = app->appId(); | ||
2691 | 1244 | lastFailedType = type; | ||
2692 | 1245 | }); | ||
2693 | 1246 | |||
2694 | 1193 | GDBusConnection* session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | 1247 | GDBusConnection* session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2695 | 1194 | 1248 | ||
2696 | 1195 | EXPECT_TRUE(ubuntu_app_launch_observer_add_app_failed(failed_observer, &last_observer)); | ||
2697 | 1196 | |||
2698 | 1197 | g_dbus_connection_emit_signal( | 1249 | g_dbus_connection_emit_signal( |
2699 | 1198 | session, NULL, /* destination */ | 1250 | session, NULL, /* destination */ |
2700 | 1199 | "/", /* path */ | 1251 | "/", /* path */ |
2701 | @@ -1202,9 +1254,10 @@ | |||
2702 | 1202 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "crash"), /* params, the same */ | 1254 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "crash"), /* params, the same */ |
2703 | 1203 | NULL); | 1255 | NULL); |
2704 | 1204 | 1256 | ||
2706 | 1205 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", last_observer); | 1257 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), lastFailedApp); |
2707 | 1258 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::Registry::FailureType::CRASH, lastFailedType); | ||
2708 | 1206 | 1259 | ||
2710 | 1207 | last_observer.clear(); | 1260 | lastFailedApp = ubuntu::app_launch::AppID(); |
2711 | 1208 | 1261 | ||
2712 | 1209 | g_dbus_connection_emit_signal( | 1262 | g_dbus_connection_emit_signal( |
2713 | 1210 | session, NULL, /* destination */ | 1263 | session, NULL, /* destination */ |
2714 | @@ -1214,9 +1267,9 @@ | |||
2715 | 1214 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "blahblah"), /* params, the same */ | 1267 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "blahblah"), /* params, the same */ |
2716 | 1215 | NULL); | 1268 | NULL); |
2717 | 1216 | 1269 | ||
2719 | 1217 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", last_observer); | 1270 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), lastFailedApp); |
2720 | 1218 | 1271 | ||
2722 | 1219 | last_observer.clear(); | 1272 | lastFailedApp = ubuntu::app_launch::AppID(); |
2723 | 1220 | 1273 | ||
2724 | 1221 | g_dbus_connection_emit_signal( | 1274 | g_dbus_connection_emit_signal( |
2725 | 1222 | session, NULL, /* destination */ | 1275 | session, NULL, /* destination */ |
2726 | @@ -1226,9 +1279,7 @@ | |||
2727 | 1226 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "start-failure"), /* params, the same */ | 1279 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "start-failure"), /* params, the same */ |
2728 | 1227 | NULL); | 1280 | NULL); |
2729 | 1228 | 1281 | ||
2733 | 1229 | EXPECT_EVENTUALLY_EQ(true, last_observer.empty()); | 1282 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::Registry::FailureType::START_FAILURE, lastFailedType); |
2731 | 1230 | |||
2732 | 1231 | EXPECT_TRUE(ubuntu_app_launch_observer_delete_app_failed(failed_observer, &last_observer)); | ||
2734 | 1232 | 1283 | ||
2735 | 1233 | g_object_unref(session); | 1284 | g_object_unref(session); |
2736 | 1234 | } | 1285 | } |
2737 | 1235 | 1286 | ||
2738 | === modified file 'tools/CMakeLists.txt' | |||
2739 | --- tools/CMakeLists.txt 2016-06-18 18:24:27 +0000 | |||
2740 | +++ tools/CMakeLists.txt 2017-01-24 04:21:42 +0000 | |||
2741 | @@ -39,7 +39,7 @@ | |||
2742 | 39 | # ubuntu-app-launch | 39 | # ubuntu-app-launch |
2743 | 40 | ######################## | 40 | ######################## |
2744 | 41 | 41 | ||
2746 | 42 | add_executable(ubuntu-app-launch ubuntu-app-launch.c) | 42 | add_executable(ubuntu-app-launch ubuntu-app-launch.cpp) |
2747 | 43 | set_target_properties(ubuntu-app-launch PROPERTIES OUTPUT_NAME "ubuntu-app-launch") | 43 | set_target_properties(ubuntu-app-launch PROPERTIES OUTPUT_NAME "ubuntu-app-launch") |
2748 | 44 | target_link_libraries(ubuntu-app-launch ubuntu-launcher) | 44 | target_link_libraries(ubuntu-app-launch ubuntu-launcher) |
2749 | 45 | install(TARGETS ubuntu-app-launch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") | 45 | install(TARGETS ubuntu-app-launch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
2750 | @@ -48,7 +48,7 @@ | |||
2751 | 48 | # ubuntu-app-watch | 48 | # ubuntu-app-watch |
2752 | 49 | ######################## | 49 | ######################## |
2753 | 50 | 50 | ||
2755 | 51 | add_executable(ubuntu-app-watch ubuntu-app-watch.c) | 51 | add_executable(ubuntu-app-watch ubuntu-app-watch.cpp) |
2756 | 52 | set_target_properties(ubuntu-app-watch PROPERTIES OUTPUT_NAME "ubuntu-app-watch") | 52 | set_target_properties(ubuntu-app-watch PROPERTIES OUTPUT_NAME "ubuntu-app-watch") |
2757 | 53 | target_link_libraries(ubuntu-app-watch ubuntu-launcher) | 53 | target_link_libraries(ubuntu-app-watch ubuntu-launcher) |
2758 | 54 | install(TARGETS ubuntu-app-watch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") | 54 | install(TARGETS ubuntu-app-watch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
2759 | @@ -116,3 +116,22 @@ | |||
2760 | 116 | target_link_libraries(ubuntu-app-usage ubuntu-launcher) | 116 | target_link_libraries(ubuntu-app-usage ubuntu-launcher) |
2761 | 117 | install(TARGETS ubuntu-app-usage RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") | 117 | install(TARGETS ubuntu-app-usage RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
2762 | 118 | 118 | ||
2763 | 119 | ######################## | ||
2764 | 120 | # Formatting | ||
2765 | 121 | ######################## | ||
2766 | 122 | |||
2767 | 123 | add_custom_target(format-tools | ||
2768 | 124 | COMMAND clang-format -i -style=file | ||
2769 | 125 | ubuntu-app-info.cpp | ||
2770 | 126 | ubuntu-app-launch-appids.cpp | ||
2771 | 127 | ubuntu-app-launch.cpp | ||
2772 | 128 | ubuntu-app-list.cpp | ||
2773 | 129 | ubuntu-app-list-pids.cpp | ||
2774 | 130 | ubuntu-app-pid.cpp | ||
2775 | 131 | ubuntu-app-stop.cpp | ||
2776 | 132 | ubuntu-app-triplet.cpp | ||
2777 | 133 | ubuntu-app-watch.cpp | ||
2778 | 134 | ubuntu-helper-list.cpp | ||
2779 | 135 | ubuntu-helper-start.cpp | ||
2780 | 136 | ubuntu-helper-stop.cpp | ||
2781 | 137 | ) | ||
2782 | 119 | 138 | ||
2783 | === modified file 'tools/ubuntu-app-info.cpp' | |||
2784 | --- tools/ubuntu-app-info.cpp 2016-05-04 14:09:10 +0000 | |||
2785 | +++ tools/ubuntu-app-info.cpp 2017-01-24 04:21:42 +0000 | |||
2786 | @@ -17,34 +17,40 @@ | |||
2787 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
2788 | 18 | */ | 18 | */ |
2789 | 19 | 19 | ||
2790 | 20 | #include <iostream> | ||
2791 | 21 | #include "libubuntu-app-launch/application.h" | 20 | #include "libubuntu-app-launch/application.h" |
2792 | 22 | #include "libubuntu-app-launch/registry.h" | 21 | #include "libubuntu-app-launch/registry.h" |
2793 | 22 | #include <iostream> | ||
2794 | 23 | 23 | ||
2796 | 24 | int main(int argc, char* argv[]) | 24 | int main(int argc, char *argv[]) |
2797 | 25 | { | 25 | { |
2799 | 26 | if (argc != 2) { | 26 | if (argc != 2) |
2800 | 27 | { | ||
2801 | 27 | std::cerr << "Usage: " << argv[0] << " (appid)" << std::endl; | 28 | std::cerr << "Usage: " << argv[0] << " (appid)" << std::endl; |
2802 | 28 | exit(1); | 29 | exit(1); |
2803 | 29 | } | 30 | } |
2804 | 30 | 31 | ||
2805 | 31 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); | 32 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); |
2807 | 32 | if (appid.empty()) { | 33 | if (appid.empty()) |
2808 | 34 | { | ||
2809 | 33 | std::cerr << "Unable to find app for appid: " << argv[1] << std::endl; | 35 | std::cerr << "Unable to find app for appid: " << argv[1] << std::endl; |
2810 | 34 | return 1; | 36 | return 1; |
2811 | 35 | } | 37 | } |
2812 | 36 | 38 | ||
2813 | 37 | std::shared_ptr<ubuntu::app_launch::Application> app; | 39 | std::shared_ptr<ubuntu::app_launch::Application> app; |
2815 | 38 | try { | 40 | try |
2816 | 41 | { | ||
2817 | 39 | app = ubuntu::app_launch::Application::create(appid, ubuntu::app_launch::Registry::getDefault()); | 42 | app = ubuntu::app_launch::Application::create(appid, ubuntu::app_launch::Registry::getDefault()); |
2818 | 40 | if (!app) | 43 | if (!app) |
2819 | 41 | throw std::runtime_error("Application object is nullptr"); | 44 | throw std::runtime_error("Application object is nullptr"); |
2821 | 42 | } catch (std::runtime_error &e) { | 45 | } |
2822 | 46 | catch (std::runtime_error &e) | ||
2823 | 47 | { | ||
2824 | 43 | std::cerr << "Unable to find application for AppID: " << argv[1] << std::endl; | 48 | std::cerr << "Unable to find application for AppID: " << argv[1] << std::endl; |
2825 | 44 | exit(1); | 49 | exit(1); |
2826 | 45 | } | 50 | } |
2827 | 46 | 51 | ||
2829 | 47 | try { | 52 | try |
2830 | 53 | { | ||
2831 | 48 | auto info = app->info(); | 54 | auto info = app->info(); |
2832 | 49 | 55 | ||
2833 | 50 | std::cout << "Name: " << info->name().value() << std::endl; | 56 | std::cout << "Name: " << info->name().value() << std::endl; |
2834 | @@ -64,8 +70,11 @@ | |||
2835 | 64 | std::cout << " Inv Landscape: " << info->supportedOrientations().invertedLandscape << std::endl; | 70 | std::cout << " Inv Landscape: " << info->supportedOrientations().invertedLandscape << std::endl; |
2836 | 65 | std::cout << "Rotates: " << info->rotatesWindowContents().value() << std::endl; | 71 | std::cout << "Rotates: " << info->rotatesWindowContents().value() << std::endl; |
2837 | 66 | std::cout << "Ubuntu Lifecycle: " << info->supportsUbuntuLifecycle().value() << std::endl; | 72 | std::cout << "Ubuntu Lifecycle: " << info->supportsUbuntuLifecycle().value() << std::endl; |
2840 | 67 | } catch (std::runtime_error &e) { | 73 | } |
2841 | 68 | std::cerr << "Unable to parse Application info for application '" << std::string(appid) << "': " << e.what() << std::endl; | 74 | catch (std::runtime_error &e) |
2842 | 75 | { | ||
2843 | 76 | std::cerr << "Unable to parse Application info for application '" << std::string(appid) << "': " << e.what() | ||
2844 | 77 | << std::endl; | ||
2845 | 69 | exit(1); | 78 | exit(1); |
2846 | 70 | } | 79 | } |
2847 | 71 | 80 | ||
2848 | 72 | 81 | ||
2849 | === renamed file 'tools/ubuntu-app-launch.c' => 'tools/ubuntu-app-launch.cpp' | |||
2850 | --- tools/ubuntu-app-launch.c 2016-02-08 19:03:31 +0000 | |||
2851 | +++ tools/ubuntu-app-launch.cpp 2017-01-24 04:21:42 +0000 | |||
2852 | @@ -1,5 +1,5 @@ | |||
2853 | 1 | /* | 1 | /* |
2855 | 2 | * Copyright 2013 Canonical Ltd. | 2 | * Copyright © 2016 Canonical Ltd. |
2856 | 3 | * | 3 | * |
2857 | 4 | * This program is free software: you can redistribute it and/or modify it | 4 | * This program is free software: you can redistribute it and/or modify it |
2858 | 5 | * under the terms of the GNU General Public License version 3, as published | 5 | * under the terms of the GNU General Public License version 3, as published |
2859 | @@ -17,71 +17,59 @@ | |||
2860 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
2861 | 18 | */ | 18 | */ |
2862 | 19 | 19 | ||
2930 | 20 | #include <glib.h> | 20 | #include "libubuntu-app-launch/application.h" |
2931 | 21 | #include "libubuntu-app-launch/ubuntu-app-launch.h" | 21 | #include "libubuntu-app-launch/registry.h" |
2932 | 22 | 22 | #include <csignal> | |
2933 | 23 | const gchar * global_appid = NULL; | 23 | #include <future> |
2934 | 24 | int retval = 0; | 24 | #include <iostream> |
2935 | 25 | 25 | ||
2936 | 26 | static void | 26 | ubuntu::app_launch::AppID global_appid; |
2937 | 27 | good_observer (const gchar * appid, gpointer user_data) | 27 | std::promise<int> retval; |
2938 | 28 | { | 28 | |
2939 | 29 | if (g_strcmp0(appid, global_appid) != 0) { | 29 | int main(int argc, char* argv[]) |
2940 | 30 | return; | 30 | { |
2941 | 31 | } | 31 | if (argc < 2) |
2942 | 32 | 32 | { | |
2943 | 33 | g_debug("Application '%s' running", appid); | 33 | std::cerr << "Usage: " << argv[0] << " <app id> [uris]" << std::endl; |
2944 | 34 | g_main_loop_quit((GMainLoop *)user_data); | 34 | return 1; |
2945 | 35 | } | 35 | } |
2946 | 36 | 36 | ||
2947 | 37 | static void | 37 | global_appid = ubuntu::app_launch::AppID::find(argv[1]); |
2948 | 38 | bad_observer (const gchar * appid, UbuntuAppLaunchAppFailed failure_type, gpointer user_data) | 38 | |
2949 | 39 | { | 39 | std::vector<ubuntu::app_launch::Application::URL> urls; |
2950 | 40 | if (g_strcmp0(appid, global_appid) != 0) { | 40 | for (int i = 2; i < argc; i++) |
2951 | 41 | return; | 41 | { |
2952 | 42 | } | 42 | urls.push_back(ubuntu::app_launch::Application::URL::from_raw(argv[i])); |
2953 | 43 | 43 | } | |
2954 | 44 | g_debug("Application '%s' failed: %s", appid, failure_type == UBUNTU_APP_LAUNCH_APP_FAILED_CRASH ? "crash" : "startup failure"); | 44 | |
2955 | 45 | retval = -1; | 45 | ubuntu::app_launch::Registry::appStarted().connect( |
2956 | 46 | g_main_loop_quit((GMainLoop *)user_data); | 46 | [](std::shared_ptr<ubuntu::app_launch::Application> app, |
2957 | 47 | } | 47 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { |
2958 | 48 | 48 | if (app->appId() != global_appid) | |
2959 | 49 | int | 49 | { |
2960 | 50 | main (int argc, gchar * argv[]) { | 50 | return; |
2961 | 51 | if (argc < 2) { | 51 | } |
2962 | 52 | g_printerr("Usage: %s <app id> [uris]\n", argv[0]); | 52 | |
2963 | 53 | return 1; | 53 | std::cout << "Started: " << (std::string)app->appId() << std::endl; |
2964 | 54 | } | 54 | retval.set_value(EXIT_SUCCESS); |
2965 | 55 | 55 | }); | |
2966 | 56 | global_appid = argv[1]; | 56 | |
2967 | 57 | GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); | 57 | ubuntu::app_launch::Registry::appFailed().connect( |
2968 | 58 | 58 | [](std::shared_ptr<ubuntu::app_launch::Application> app, | |
2969 | 59 | gchar ** uris = NULL; | 59 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
2970 | 60 | if (argc > 2) { | 60 | ubuntu::app_launch::Registry::FailureType type) { |
2971 | 61 | int i; | 61 | if (app->appId() != global_appid) |
2972 | 62 | 62 | { | |
2973 | 63 | uris = g_new0(gchar *, argc - 1); | 63 | return; |
2974 | 64 | 64 | } | |
2975 | 65 | for (i = 2; i < argc; i++) { | 65 | |
2976 | 66 | uris[i - 2] = argv[i]; | 66 | std::cout << "Failed: " << (std::string)app->appId() << std::endl; |
2977 | 67 | } | 67 | retval.set_value(EXIT_FAILURE); |
2978 | 68 | } | 68 | }); |
2979 | 69 | 69 | ||
2980 | 70 | ubuntu_app_launch_observer_add_app_started(good_observer, mainloop); | 70 | auto app = ubuntu::app_launch::Application::create(global_appid, ubuntu::app_launch::Registry::getDefault()); |
2981 | 71 | ubuntu_app_launch_observer_add_app_focus(good_observer, mainloop); | 71 | app->launch(urls); |
2982 | 72 | 72 | ||
2983 | 73 | ubuntu_app_launch_observer_add_app_failed(bad_observer, mainloop); | 73 | std::signal(SIGTERM, [](int signal) -> void { retval.set_value(EXIT_SUCCESS); }); |
2984 | 74 | 74 | return retval.get_future().get(); | |
2918 | 75 | ubuntu_app_launch_start_application(global_appid, (const gchar * const *)uris); | ||
2919 | 76 | |||
2920 | 77 | g_main_loop_run(mainloop); | ||
2921 | 78 | |||
2922 | 79 | ubuntu_app_launch_observer_delete_app_started(good_observer, mainloop); | ||
2923 | 80 | ubuntu_app_launch_observer_delete_app_focus(good_observer, mainloop); | ||
2924 | 81 | ubuntu_app_launch_observer_delete_app_failed(bad_observer, mainloop); | ||
2925 | 82 | |||
2926 | 83 | g_main_loop_unref(mainloop); | ||
2927 | 84 | g_free(uris); | ||
2928 | 85 | |||
2929 | 86 | return retval; | ||
2985 | 87 | } | 75 | } |
2986 | 88 | 76 | ||
2987 | === modified file 'tools/ubuntu-app-list-pids.cpp' | |||
2988 | --- tools/ubuntu-app-list-pids.cpp 2016-05-03 01:46:27 +0000 | |||
2989 | +++ tools/ubuntu-app-list-pids.cpp 2017-01-24 04:21:42 +0000 | |||
2990 | @@ -30,12 +30,14 @@ | |||
2991 | 30 | } | 30 | } |
2992 | 31 | 31 | ||
2993 | 32 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); | 32 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); |
2995 | 33 | if (appid.empty()) { | 33 | if (appid.empty()) |
2996 | 34 | { | ||
2997 | 34 | std::cerr << "Unable to find app for appid: " << argv[1] << std::endl; | 35 | std::cerr << "Unable to find app for appid: " << argv[1] << std::endl; |
2998 | 35 | return 1; | 36 | return 1; |
2999 | 36 | } | 37 | } |
3000 | 37 | 38 | ||
3002 | 38 | try { | 39 | try |
3003 | 40 | { | ||
3004 | 39 | auto app = ubuntu::app_launch::Application::create(appid, ubuntu::app_launch::Registry::getDefault()); | 41 | auto app = ubuntu::app_launch::Application::create(appid, ubuntu::app_launch::Registry::getDefault()); |
3005 | 40 | 42 | ||
3006 | 41 | for (auto instance : app->instances()) | 43 | for (auto instance : app->instances()) |
3007 | @@ -45,7 +47,9 @@ | |||
3008 | 45 | std::cout << pid << std::endl; | 47 | std::cout << pid << std::endl; |
3009 | 46 | } | 48 | } |
3010 | 47 | } | 49 | } |
3012 | 48 | } catch (std::runtime_error &e) { | 50 | } |
3013 | 51 | catch (std::runtime_error& e) | ||
3014 | 52 | { | ||
3015 | 49 | std::cerr << "Unable to find application for '" << std::string(appid) << "': " << e.what() << std::endl; | 53 | std::cerr << "Unable to find application for '" << std::string(appid) << "': " << e.what() << std::endl; |
3016 | 50 | return 1; | 54 | return 1; |
3017 | 51 | } | 55 | } |
3018 | 52 | 56 | ||
3019 | === modified file 'tools/ubuntu-app-list.cpp' | |||
3020 | --- tools/ubuntu-app-list.cpp 2016-02-09 21:12:54 +0000 | |||
3021 | +++ tools/ubuntu-app-list.cpp 2017-01-24 04:21:42 +0000 | |||
3022 | @@ -17,8 +17,8 @@ | |||
3023 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
3024 | 18 | */ | 18 | */ |
3025 | 19 | 19 | ||
3026 | 20 | #include "libubuntu-app-launch/registry.h" | ||
3027 | 20 | #include <iostream> | 21 | #include <iostream> |
3028 | 21 | #include "libubuntu-app-launch/registry.h" | ||
3029 | 22 | 22 | ||
3030 | 23 | int main(int argc, char* argv[]) | 23 | int main(int argc, char* argv[]) |
3031 | 24 | { | 24 | { |
3032 | 25 | 25 | ||
3033 | === modified file 'tools/ubuntu-app-pid.cpp' | |||
3034 | --- tools/ubuntu-app-pid.cpp 2016-05-03 01:46:51 +0000 | |||
3035 | +++ tools/ubuntu-app-pid.cpp 2017-01-24 04:21:42 +0000 | |||
3036 | @@ -18,8 +18,8 @@ | |||
3037 | 18 | */ | 18 | */ |
3038 | 19 | 19 | ||
3039 | 20 | #include <iostream> | 20 | #include <iostream> |
3040 | 21 | #include <libubuntu-app-launch/application.h> | ||
3041 | 21 | #include <libubuntu-app-launch/registry.h> | 22 | #include <libubuntu-app-launch/registry.h> |
3042 | 22 | #include <libubuntu-app-launch/application.h> | ||
3043 | 23 | 23 | ||
3044 | 24 | int main(int argc, char* argv[]) | 24 | int main(int argc, char* argv[]) |
3045 | 25 | { | 25 | { |
3046 | @@ -31,12 +31,14 @@ | |||
3047 | 31 | } | 31 | } |
3048 | 32 | 32 | ||
3049 | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); |
3051 | 34 | if (appid.empty()) { | 34 | if (appid.empty()) |
3052 | 35 | { | ||
3053 | 35 | std::cerr << "Unable to find app for appid: " << argv[1] << std::endl; | 36 | std::cerr << "Unable to find app for appid: " << argv[1] << std::endl; |
3054 | 36 | return 1; | 37 | return 1; |
3055 | 37 | } | 38 | } |
3056 | 38 | 39 | ||
3058 | 39 | try { | 40 | try |
3059 | 41 | { | ||
3060 | 40 | auto app = ubuntu::app_launch::Application::create(appid, ubuntu::app_launch::Registry::getDefault()); | 42 | auto app = ubuntu::app_launch::Application::create(appid, ubuntu::app_launch::Registry::getDefault()); |
3061 | 41 | auto pid = app->instances()[0]->primaryPid(); | 43 | auto pid = app->instances()[0]->primaryPid(); |
3062 | 42 | 44 | ||
3063 | @@ -47,7 +49,9 @@ | |||
3064 | 47 | 49 | ||
3065 | 48 | std::cout << pid << std::endl; | 50 | std::cout << pid << std::endl; |
3066 | 49 | return 0; | 51 | return 0; |
3068 | 50 | } catch (std::runtime_error &e) { | 52 | } |
3069 | 53 | catch (std::runtime_error& e) | ||
3070 | 54 | { | ||
3071 | 51 | std::cerr << "Unable to find application for '" << std::string(appid) << "': " << e.what() << std::endl; | 55 | std::cerr << "Unable to find application for '" << std::string(appid) << "': " << e.what() << std::endl; |
3072 | 52 | return 1; | 56 | return 1; |
3073 | 53 | } | 57 | } |
3074 | 54 | 58 | ||
3075 | === modified file 'tools/ubuntu-app-stop.cpp' | |||
3076 | --- tools/ubuntu-app-stop.cpp 2016-05-03 01:46:27 +0000 | |||
3077 | +++ tools/ubuntu-app-stop.cpp 2017-01-24 04:21:42 +0000 | |||
3078 | @@ -30,19 +30,23 @@ | |||
3079 | 30 | } | 30 | } |
3080 | 31 | 31 | ||
3081 | 32 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); | 32 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); |
3083 | 33 | if (appid.empty()) { | 33 | if (appid.empty()) |
3084 | 34 | { | ||
3085 | 34 | std::cerr << "Unable to find app for appid: " << argv[1] << std::endl; | 35 | std::cerr << "Unable to find app for appid: " << argv[1] << std::endl; |
3086 | 35 | return 1; | 36 | return 1; |
3087 | 36 | } | 37 | } |
3088 | 37 | 38 | ||
3090 | 38 | try { | 39 | try |
3091 | 40 | { | ||
3092 | 39 | auto app = ubuntu::app_launch::Application::create(appid, ubuntu::app_launch::Registry::getDefault()); | 41 | auto app = ubuntu::app_launch::Application::create(appid, ubuntu::app_launch::Registry::getDefault()); |
3093 | 40 | 42 | ||
3094 | 41 | for (auto instance : app->instances()) | 43 | for (auto instance : app->instances()) |
3095 | 42 | { | 44 | { |
3096 | 43 | instance->stop(); | 45 | instance->stop(); |
3097 | 44 | } | 46 | } |
3099 | 45 | } catch (std::runtime_error &e) { | 47 | } |
3100 | 48 | catch (std::runtime_error& e) | ||
3101 | 49 | { | ||
3102 | 46 | std::cerr << "Unable to find application for '" << std::string(appid) << "': " << e.what() << std::endl; | 50 | std::cerr << "Unable to find application for '" << std::string(appid) << "': " << e.what() << std::endl; |
3103 | 47 | return 1; | 51 | return 1; |
3104 | 48 | } | 52 | } |
3105 | 49 | 53 | ||
3106 | === modified file 'tools/ubuntu-app-triplet.cpp' | |||
3107 | --- tools/ubuntu-app-triplet.cpp 2016-02-09 21:12:54 +0000 | |||
3108 | +++ tools/ubuntu-app-triplet.cpp 2017-01-24 04:21:42 +0000 | |||
3109 | @@ -17,8 +17,8 @@ | |||
3110 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
3111 | 18 | */ | 18 | */ |
3112 | 19 | 19 | ||
3113 | 20 | #include "libubuntu-app-launch/application.h" | ||
3114 | 20 | #include <iostream> | 21 | #include <iostream> |
3115 | 21 | #include "libubuntu-app-launch/application.h" | ||
3116 | 22 | 22 | ||
3117 | 23 | int main(int argc, char* argv[]) | 23 | int main(int argc, char* argv[]) |
3118 | 24 | { | 24 | { |
3119 | 25 | 25 | ||
3120 | === renamed file 'tools/ubuntu-app-watch.c' => 'tools/ubuntu-app-watch.cpp' | |||
3121 | --- tools/ubuntu-app-watch.c 2016-02-08 19:03:31 +0000 | |||
3122 | +++ tools/ubuntu-app-watch.cpp 2017-01-24 04:21:42 +0000 | |||
3123 | @@ -1,5 +1,5 @@ | |||
3124 | 1 | /* | 1 | /* |
3126 | 2 | * Copyright 2013 Canonical Ltd. | 2 | * Copyright © 2015 Canonical Ltd. |
3127 | 3 | * | 3 | * |
3128 | 4 | * This program is free software: you can redistribute it and/or modify it | 4 | * This program is free software: you can redistribute it and/or modify it |
3129 | 5 | * under the terms of the GNU General Public License version 3, as published | 5 | * under the terms of the GNU General Public License version 3, as published |
3130 | @@ -17,91 +17,64 @@ | |||
3131 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
3132 | 18 | */ | 18 | */ |
3133 | 19 | 19 | ||
3221 | 20 | #include "libubuntu-app-launch/ubuntu-app-launch.h" | 20 | #include "libubuntu-app-launch/registry.h" |
3222 | 21 | 21 | #include <csignal> | |
3223 | 22 | void | 22 | #include <future> |
3224 | 23 | starting (const gchar * appid, gpointer user_data) | 23 | |
3225 | 24 | { | 24 | std::promise<int> retval; |
3226 | 25 | g_print("Starting %s\n", appid); | 25 | |
3227 | 26 | return; | 26 | int main(int argc, char* argv[]) |
3228 | 27 | } | 27 | { |
3229 | 28 | 28 | ubuntu::app_launch::Registry registry; | |
3230 | 29 | void | 29 | |
3231 | 30 | started (const gchar * appid, gpointer user_data) | 30 | registry.appStarted().connect([](const std::shared_ptr<ubuntu::app_launch::Application>& app, |
3232 | 31 | { | 31 | const std::shared_ptr<ubuntu::app_launch::Application::Instance>& instance) { |
3233 | 32 | g_print("Started %s\n", appid); | 32 | std::cout << "Started: " << (std::string)app->appId() << std::endl; |
3234 | 33 | return; | 33 | }); |
3235 | 34 | } | 34 | registry.appStopped().connect([](const std::shared_ptr<ubuntu::app_launch::Application>& app, |
3236 | 35 | 35 | const std::shared_ptr<ubuntu::app_launch::Application::Instance>& instance) { | |
3237 | 36 | void | 36 | std::cout << "Stopped: " << (std::string)app->appId() << std::endl; |
3238 | 37 | stopped (const gchar * appid, gpointer user_data) | 37 | }); |
3239 | 38 | { | 38 | registry.appPaused().connect([](const std::shared_ptr<ubuntu::app_launch::Application>& app, |
3240 | 39 | g_print("Stop %s\n", appid); | 39 | const std::shared_ptr<ubuntu::app_launch::Application::Instance>& instance, |
3241 | 40 | return; | 40 | const std::vector<pid_t>& pids) { |
3242 | 41 | } | 41 | std::cout << "Paused: " << (std::string)app->appId() << " ("; |
3243 | 42 | 42 | ||
3244 | 43 | void | 43 | for (auto pid : pids) |
3245 | 44 | resumed (const gchar * appid, GPid * pids, gpointer user_data) | 44 | { |
3246 | 45 | { | 45 | std::cout << std::to_string(pid) << " "; |
3247 | 46 | g_print("Resumed %s\n", appid); | 46 | } |
3248 | 47 | return; | 47 | |
3249 | 48 | } | 48 | std::cout << ")" << std::endl; |
3250 | 49 | 49 | }); | |
3251 | 50 | void | 50 | registry.appResumed().connect([](const std::shared_ptr<ubuntu::app_launch::Application>& app, |
3252 | 51 | paused (const gchar * appid, GPid * pids, gpointer user_data) | 51 | const std::shared_ptr<ubuntu::app_launch::Application::Instance>& instance, |
3253 | 52 | { | 52 | const std::vector<pid_t>& pids) { |
3254 | 53 | g_print("Paused %s\n", appid); | 53 | std::cout << "Resumed: " << (std::string)app->appId() << " ("; |
3255 | 54 | return; | 54 | |
3256 | 55 | } | 55 | for (auto pid : pids) |
3257 | 56 | 56 | { | |
3258 | 57 | void | 57 | std::cout << std::to_string(pid) << " "; |
3259 | 58 | focus (const gchar * appid, gpointer user_data) | 58 | } |
3260 | 59 | { | 59 | |
3261 | 60 | g_print("Focus %s\n", appid); | 60 | std::cout << ")" << std::endl; |
3262 | 61 | return; | 61 | }); |
3263 | 62 | } | 62 | registry.appFailed().connect([](const std::shared_ptr<ubuntu::app_launch::Application>& app, |
3264 | 63 | 63 | const std::shared_ptr<ubuntu::app_launch::Application::Instance>& instance, | |
3265 | 64 | void | 64 | ubuntu::app_launch::Registry::FailureType type) { |
3266 | 65 | fail (const gchar * appid, UbuntuAppLaunchAppFailed failhow, gpointer user_data) | 65 | std::cout << "Failed: " << (std::string)app->appId(); |
3267 | 66 | { | 66 | switch (type) |
3268 | 67 | const gchar * failstr = "unknown"; | 67 | { |
3269 | 68 | switch (failhow) { | 68 | case ubuntu::app_launch::Registry::FailureType::CRASH: |
3270 | 69 | case UBUNTU_APP_LAUNCH_APP_FAILED_CRASH: | 69 | std::cout << " (crash)"; |
3271 | 70 | failstr = "crashed"; | 70 | break; |
3272 | 71 | break; | 71 | case ubuntu::app_launch::Registry::FailureType::START_FAILURE: |
3273 | 72 | case UBUNTU_APP_LAUNCH_APP_FAILED_START_FAILURE: | 72 | std::cout << " (start failure)"; |
3274 | 73 | failstr = "startup"; | 73 | break; |
3275 | 74 | break; | 74 | } |
3276 | 75 | } | 75 | std::cout << std::endl; |
3277 | 76 | 76 | }); | |
3278 | 77 | g_print("Fail %s (%s)\n", appid, failstr); | 77 | |
3279 | 78 | return; | 78 | std::signal(SIGTERM, [](int signal) -> void { retval.set_value(EXIT_SUCCESS); }); |
3280 | 79 | } | 79 | return retval.get_future().get(); |
3194 | 80 | |||
3195 | 81 | |||
3196 | 82 | int | ||
3197 | 83 | main (int argc, gchar * argv[]) | ||
3198 | 84 | { | ||
3199 | 85 | ubuntu_app_launch_observer_add_app_starting(starting, NULL); | ||
3200 | 86 | ubuntu_app_launch_observer_add_app_started(started, NULL); | ||
3201 | 87 | ubuntu_app_launch_observer_add_app_stop(stopped, NULL); | ||
3202 | 88 | ubuntu_app_launch_observer_add_app_focus(focus, NULL); | ||
3203 | 89 | ubuntu_app_launch_observer_add_app_resumed(resumed, NULL); | ||
3204 | 90 | ubuntu_app_launch_observer_add_app_paused(paused, NULL); | ||
3205 | 91 | ubuntu_app_launch_observer_add_app_failed(fail, NULL); | ||
3206 | 92 | |||
3207 | 93 | GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); | ||
3208 | 94 | g_main_loop_run(mainloop); | ||
3209 | 95 | |||
3210 | 96 | ubuntu_app_launch_observer_delete_app_starting(starting, NULL); | ||
3211 | 97 | ubuntu_app_launch_observer_delete_app_started(started, NULL); | ||
3212 | 98 | ubuntu_app_launch_observer_delete_app_stop(stopped, NULL); | ||
3213 | 99 | ubuntu_app_launch_observer_delete_app_focus(focus, NULL); | ||
3214 | 100 | ubuntu_app_launch_observer_delete_app_resumed(resumed, NULL); | ||
3215 | 101 | ubuntu_app_launch_observer_delete_app_paused(paused, NULL); | ||
3216 | 102 | ubuntu_app_launch_observer_delete_app_failed(fail, NULL); | ||
3217 | 103 | |||
3218 | 104 | g_main_loop_unref(mainloop); | ||
3219 | 105 | |||
3220 | 106 | return 0; | ||
3281 | 107 | } | 80 | } |
3282 | 108 | 81 | ||
3283 | === modified file 'tools/ubuntu-helper-list.cpp' | |||
3284 | --- tools/ubuntu-helper-list.cpp 2016-02-09 21:12:54 +0000 | |||
3285 | +++ tools/ubuntu-helper-list.cpp 2017-01-24 04:21:42 +0000 | |||
3286 | @@ -17,8 +17,8 @@ | |||
3287 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
3288 | 18 | */ | 18 | */ |
3289 | 19 | 19 | ||
3290 | 20 | #include "libubuntu-app-launch/registry.h" | ||
3291 | 20 | #include <iostream> | 21 | #include <iostream> |
3292 | 21 | #include "libubuntu-app-launch/registry.h" | ||
3293 | 22 | 22 | ||
3294 | 23 | int main(int argc, char* argv[]) | 23 | int main(int argc, char* argv[]) |
3295 | 24 | { | 24 | { |
3296 | 25 | 25 | ||
3297 | === modified file 'tools/ubuntu-helper-start.cpp' | |||
3298 | --- tools/ubuntu-helper-start.cpp 2016-05-03 01:46:27 +0000 | |||
3299 | +++ tools/ubuntu-helper-start.cpp 2017-01-24 04:21:42 +0000 | |||
3300 | @@ -17,9 +17,9 @@ | |||
3301 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
3302 | 18 | */ | 18 | */ |
3303 | 19 | 19 | ||
3304 | 20 | #include <iostream> | ||
3305 | 21 | #include "libubuntu-app-launch/helper.h" | 20 | #include "libubuntu-app-launch/helper.h" |
3306 | 22 | #include "libubuntu-app-launch/registry.h" | 21 | #include "libubuntu-app-launch/registry.h" |
3307 | 22 | #include <iostream> | ||
3308 | 23 | 23 | ||
3309 | 24 | int main(int argc, char* argv[]) | 24 | int main(int argc, char* argv[]) |
3310 | 25 | { | 25 | { |
3311 | @@ -31,20 +31,25 @@ | |||
3312 | 31 | 31 | ||
3313 | 32 | auto type = ubuntu::app_launch::Helper::Type::from_raw(argv[1]); | 32 | auto type = ubuntu::app_launch::Helper::Type::from_raw(argv[1]); |
3314 | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[2]); | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[2]); |
3316 | 34 | if (appid.empty()) { | 34 | if (appid.empty()) |
3317 | 35 | { | ||
3318 | 35 | std::cerr << "Unable to find helper for appid: " << argv[1] << std::endl; | 36 | std::cerr << "Unable to find helper for appid: " << argv[1] << std::endl; |
3319 | 36 | return 1; | 37 | return 1; |
3320 | 37 | } | 38 | } |
3321 | 38 | 39 | ||
3322 | 39 | auto registry = std::make_shared<ubuntu::app_launch::Registry>(); | 40 | auto registry = std::make_shared<ubuntu::app_launch::Registry>(); |
3323 | 40 | 41 | ||
3325 | 41 | try { | 42 | try |
3326 | 43 | { | ||
3327 | 42 | auto helper = ubuntu::app_launch::Helper::create(type, appid, registry); | 44 | auto helper = ubuntu::app_launch::Helper::create(type, appid, registry); |
3328 | 43 | 45 | ||
3329 | 44 | helper->launch(); | 46 | helper->launch(); |
3330 | 45 | return 0; | 47 | return 0; |
3333 | 46 | } catch (std::runtime_error &e) { | 48 | } |
3334 | 47 | std::cerr << "Unable to find helper for '" << std::string(appid) << "' type '" << type.value() << "': " << e.what() << std::endl; | 49 | catch (std::runtime_error& e) |
3335 | 50 | { | ||
3336 | 51 | std::cerr << "Unable to find helper for '" << std::string(appid) << "' type '" << type.value() | ||
3337 | 52 | << "': " << e.what() << std::endl; | ||
3338 | 48 | return 1; | 53 | return 1; |
3339 | 49 | } | 54 | } |
3340 | 50 | } | 55 | } |
3341 | 51 | 56 | ||
3342 | === modified file 'tools/ubuntu-helper-stop.cpp' | |||
3343 | --- tools/ubuntu-helper-stop.cpp 2016-05-03 01:46:27 +0000 | |||
3344 | +++ tools/ubuntu-helper-stop.cpp 2017-01-24 04:21:42 +0000 | |||
3345 | @@ -17,9 +17,9 @@ | |||
3346 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
3347 | 18 | */ | 18 | */ |
3348 | 19 | 19 | ||
3349 | 20 | #include <iostream> | ||
3350 | 21 | #include "libubuntu-app-launch/helper.h" | 20 | #include "libubuntu-app-launch/helper.h" |
3351 | 22 | #include "libubuntu-app-launch/registry.h" | 21 | #include "libubuntu-app-launch/registry.h" |
3352 | 22 | #include <iostream> | ||
3353 | 23 | 23 | ||
3354 | 24 | int main(int argc, char* argv[]) | 24 | int main(int argc, char* argv[]) |
3355 | 25 | { | 25 | { |
3356 | @@ -31,14 +31,16 @@ | |||
3357 | 31 | 31 | ||
3358 | 32 | auto type = ubuntu::app_launch::Helper::Type::from_raw(argv[1]); | 32 | auto type = ubuntu::app_launch::Helper::Type::from_raw(argv[1]); |
3359 | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[2]); | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[2]); |
3361 | 34 | if (appid.empty()) { | 34 | if (appid.empty()) |
3362 | 35 | { | ||
3363 | 35 | std::cerr << "Unable to find helper for appid: " << argv[1] << std::endl; | 36 | std::cerr << "Unable to find helper for appid: " << argv[1] << std::endl; |
3364 | 36 | return 1; | 37 | return 1; |
3365 | 37 | } | 38 | } |
3366 | 38 | 39 | ||
3367 | 39 | auto registry = std::make_shared<ubuntu::app_launch::Registry>(); | 40 | auto registry = std::make_shared<ubuntu::app_launch::Registry>(); |
3368 | 40 | 41 | ||
3370 | 41 | try { | 42 | try |
3371 | 43 | { | ||
3372 | 42 | auto helper = ubuntu::app_launch::Helper::create(type, appid, registry); | 44 | auto helper = ubuntu::app_launch::Helper::create(type, appid, registry); |
3373 | 43 | 45 | ||
3374 | 44 | for (auto instance : helper->instances()) | 46 | for (auto instance : helper->instances()) |
3375 | @@ -47,8 +49,11 @@ | |||
3376 | 47 | } | 49 | } |
3377 | 48 | 50 | ||
3378 | 49 | return 0; | 51 | return 0; |
3381 | 50 | } catch (std::runtime_error &e) { | 52 | } |
3382 | 51 | std::cerr << "Unable to find helper for '" << std::string(appid) << "' type '" << type.value() << "': " << e.what() << std::endl; | 53 | catch (std::runtime_error& e) |
3383 | 54 | { | ||
3384 | 55 | std::cerr << "Unable to find helper for '" << std::string(appid) << "' type '" << type.value() | ||
3385 | 56 | << "': " << e.what() << std::endl; | ||
3386 | 52 | return 1; | 57 | return 1; |
3387 | 53 | } | 58 | } |
3388 | 54 | } | 59 | } |
FAILED: Continuous integration, rev:232 /code.launchpad .net/~ted/ ubuntu- app-launch/ app-object- signals/ +merge/ 294807/ +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:/
http:// jenkins. qa.ubuntu. com/job/ ubuntu- app-launch- ci/55/ jenkins. qa.ubuntu. com/job/ ubuntu- app-launch- wily-amd64- ci/55/console jenkins. qa.ubuntu. com/job/ ubuntu- app-launch- wily-armhf- ci/55/console jenkins. qa.ubuntu. com/job/ ubuntu- app-launch- wily-i386- ci/55/console
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- app-launch- ci/55/rebuild
http://