Merge lp:~ted/ubuntu-app-launch/app-object-signals into lp:ubuntu-app-launch/16.10
- app-object-signals
- Merge into trunk.16.10
Status: | Superseded | ||||
---|---|---|---|---|---|
Proposed branch: | lp:~ted/ubuntu-app-launch/app-object-signals | ||||
Merge into: | lp:ubuntu-app-launch/16.10 | ||||
Diff against target: |
3184 lines (+1583/-880) 22 files modified
libubuntu-app-launch/application-impl-libertine.cpp (+1/-2) libubuntu-app-launch/libubuntu-app-launch.map (+1/-0) libubuntu-app-launch/registry-impl.cpp (+493/-11) libubuntu-app-launch/registry-impl.h (+76/-11) libubuntu-app-launch/registry.cpp (+42/-2) libubuntu-app-launch/registry.h (+120/-14) libubuntu-app-launch/ubuntu-app-launch.cpp (+339/-413) tests/CMakeLists.txt (+1/-0) tests/failure-test.cc (+123/-96) tests/libual-cpp-test.cc (+186/-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 |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Needs Fixing | |
Indicator Applet Developers | Pending | ||
Review via email: mp+294807@code.launchpad.net |
This proposal supersedes a proposal from 2016-02-08.
This proposal has been superseded by a proposal from 2016-11-07.
Commit message
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
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 : | # |
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://
- 236. By Ted Gould
-
Adding in stubs to bring out the implementation
- 237. By Ted Gould
-
Merging trunk
- 238. By Ted Gould
-
Move the signal functions into the implementation
- 239. By Ted Gould
-
Building a place to register signals
- 240. By Ted Gould
-
Code up starting and stopping, some TODOs
- 241. By Ted Gould
-
Port over app started and stopped to C++ interfaces
- 242. By Ted Gould
-
Switch to passing in the shared pointer to the registry
- 243. By Ted Gould
-
Make sure to grab a copy of the shared pointer
- 244. By Ted Gould
-
Move the greed around in our regex
- 245. By Ted Gould
-
Switching to a weak pointer
- 246. By Ted Gould
-
Make calls with the C library use the current context to not break existing code.
- 247. By Ted Gould
-
Moving over pause/resume
- 248. By Ted Gould
-
Fixing the watcher
- 249. By Ted Gould
-
Migrating over the failed signal
- 250. By Ted Gould
-
Apply formatting rules to tools
- 251. By Ted Gould
-
Print pids for pause/resume
- 252. By Ted Gould
-
Basic foundation for manager signals
- 253. By Ted Gould
-
Start to flesh out more of the resume request
- 254. By Ted Gould
-
Restructure to use more shared pointers
- 255. By Ted Gould
-
Switch the C code to using the manager interface
- 256. By Ted Gould
-
Fleshing out the focus handler
- 257. By Ted Gould
-
Add a handler for starting
- 258. By Ted Gould
-
Refactor into a shared function to do the longer dbus calls
- 259. By Ted Gould
-
Restructure so that we can call the right signal
- 260. By Ted Gould
-
Make it so that the manager observers execute on their context
- 261. By Ted Gould
-
Switch to using a global weak pointer so that it expires with the tracking of the Registry object
- 262. By Ted Gould
-
Clean up weak_ptr<> code
- 263. By Ted Gould
-
Make sure we wait to install the signals before returning
- 264. By Ted Gould
-
Put a warning in about thread safety
- 265. By Ted Gould
-
Port tests over to using a manager for focus events
- 266. By Ted Gould
-
Fixing the start and stop observer test
- 267. By Ted Gould
-
Fix the starting test
- 268. By Ted Gould
-
Failing test ported over
- 269. By Ted Gould
-
Documentation for registry functions
- 270. By Ted Gould
-
More comments
- 271. By Ted Gould
-
Variable comments
- 272. By Ted Gould
-
A comment on why this comment is there
- 273. By Ted Gould
-
Switch failure test over to using the C++ api
- 274. By Ted Gould
-
Making sure we connect the signals before returnning
- 275. By Ted Gould
-
Fix failure test environment and values to make them work as real applications
- 276. By Ted Gould
-
Apply formatting rules to failure-test.cc
- 277. By Ted Gould
-
Make gcc6 happy
- 278. By Ted Gould
-
Putting additional checks in to make sure we don't use null pointers we don't get locks on.
- 279. By Ted Gould
-
Ensure the manager thread shutsdown before the registry to avoid a deadlock
- 280. By Ted Gould
-
Merge future trunk
- 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
- 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
- 311. By Ted Gould
-
Update to trunk
- 312. By Ted Gould
-
Adding virtual destructors, acc says they're fine.
- 313. By Ted Gould
-
Putting this off for gcc 5.4
- 314. By Ted Gould
-
Block off more API breaks this time
Unmerged revisions
- 314. By Ted Gould
-
Block off more API breaks this time
- 313. By Ted Gould
-
Putting this off for gcc 5.4
- 312. By Ted Gould
-
Adding virtual destructors, acc says they're fine.
- 311. By Ted Gould
-
Update to trunk
- 310. By Ted Gould
-
I've been overrided by charles
- 309. By Ted Gould
-
Factor out pause/resume commonality
- 308. By Ted Gould
-
Expand the usage of observer_delete
- 307. By Ted Gould
-
Rename a function and add comments
- 306. By Ted Gould
-
Pull out the request code into individual functions
- 305. By Ted Gould
-
Putting all the map handling code in a couple templates
Preview Diff
1 | === modified file 'libubuntu-app-launch/application-impl-libertine.cpp' | |||
2 | --- libubuntu-app-launch/application-impl-libertine.cpp 2016-10-03 23:54:20 +0000 | |||
3 | +++ libubuntu-app-launch/application-impl-libertine.cpp 2016-11-07 20:56:13 +0000 | |||
4 | @@ -255,8 +255,7 @@ | |||
5 | 255 | } | 255 | } |
6 | 256 | catch (std::runtime_error& e) | 256 | catch (std::runtime_error& e) |
7 | 257 | { | 257 | { |
10 | 258 | g_debug("Unable to create application for libertine appname '%s': %s", | 258 | g_debug("Unable to create application for libertine appname '%s': %s", apps.get()[j], e.what()); |
9 | 259 | apps.get()[j], e.what()); | ||
11 | 260 | } | 259 | } |
12 | 261 | } | 260 | } |
13 | 262 | } | 261 | } |
14 | 263 | 262 | ||
15 | === modified file 'libubuntu-app-launch/libubuntu-app-launch.map' | |||
16 | --- libubuntu-app-launch/libubuntu-app-launch.map 2016-05-19 16:24:11 +0000 | |||
17 | +++ libubuntu-app-launch/libubuntu-app-launch.map 2016-11-07 20:56:13 +0000 | |||
18 | @@ -14,6 +14,7 @@ | |||
19 | 14 | ubuntu::app_launch::Helper::*; | 14 | ubuntu::app_launch::Helper::*; |
20 | 15 | typeinfo?for?ubuntu::app_launch::Helper; | 15 | typeinfo?for?ubuntu::app_launch::Helper; |
21 | 16 | typeinfo?name?for?ubuntu::app_launch::Helper; | 16 | typeinfo?name?for?ubuntu::app_launch::Helper; |
22 | 17 | ubuntu::app_launch::operator*; | ||
23 | 17 | ubuntu::app_launch::oom::*; | 18 | ubuntu::app_launch::oom::*; |
24 | 18 | }; | 19 | }; |
25 | 19 | local: | 20 | local: |
26 | 20 | 21 | ||
27 | === modified file 'libubuntu-app-launch/registry-impl.cpp' | |||
28 | --- libubuntu-app-launch/registry-impl.cpp 2016-09-23 22:30:51 +0000 | |||
29 | +++ libubuntu-app-launch/registry-impl.cpp 2016-11-07 20:56:13 +0000 | |||
30 | @@ -20,6 +20,7 @@ | |||
31 | 20 | #include "registry-impl.h" | 20 | #include "registry-impl.h" |
32 | 21 | #include "application-icon-finder.h" | 21 | #include "application-icon-finder.h" |
33 | 22 | #include <cgmanager/cgmanager.h> | 22 | #include <cgmanager/cgmanager.h> |
34 | 23 | #include <regex> | ||
35 | 23 | #include <upstart.h> | 24 | #include <upstart.h> |
36 | 24 | 25 | ||
37 | 25 | namespace ubuntu | 26 | namespace ubuntu |
38 | @@ -36,13 +37,29 @@ | |||
39 | 36 | zgLog_.reset(); | 37 | zgLog_.reset(); |
40 | 37 | cgManager_.reset(); | 38 | cgManager_.reset(); |
41 | 38 | 39 | ||
42 | 40 | auto dohandle = [&](guint& handle) { | ||
43 | 41 | if (handle != 0) | ||
44 | 42 | { | ||
45 | 43 | g_dbus_connection_signal_unsubscribe(_dbus.get(), handle); | ||
46 | 44 | handle = 0; | ||
47 | 45 | } | ||
48 | 46 | }; | ||
49 | 47 | |||
50 | 48 | dohandle(handle_appStarted); | ||
51 | 49 | dohandle(handle_appStopped); | ||
52 | 50 | dohandle(handle_appFailed); | ||
53 | 51 | dohandle(handle_appPaused); | ||
54 | 52 | dohandle(handle_appResumed); | ||
55 | 53 | dohandle(handle_managerSignalFocus); | ||
56 | 54 | dohandle(handle_managerSignalResume); | ||
57 | 55 | dohandle(handle_managerSignalStarting); | ||
58 | 56 | |||
59 | 39 | if (_dbus) | 57 | if (_dbus) |
60 | 40 | g_dbus_connection_flush_sync(_dbus.get(), nullptr, nullptr); | 58 | g_dbus_connection_flush_sync(_dbus.get(), nullptr, nullptr); |
61 | 41 | _dbus.reset(); | 59 | _dbus.reset(); |
62 | 42 | }) | 60 | }) |
63 | 43 | , _registry(registry) | 61 | , _registry(registry) |
64 | 44 | , _iconFinders() | 62 | , _iconFinders() |
65 | 45 | // _manager(nullptr) | ||
66 | 46 | { | 63 | { |
67 | 47 | auto cancel = thread.getCancellable(); | 64 | auto cancel = thread.getCancellable(); |
68 | 48 | _dbus = thread.executeOnThread<std::shared_ptr<GDBusConnection>>([cancel]() { | 65 | _dbus = thread.executeOnThread<std::shared_ptr<GDBusConnection>>([cancel]() { |
69 | @@ -536,24 +553,193 @@ | |||
70 | 536 | return _iconFinders[basePath]; | 553 | return _iconFinders[basePath]; |
71 | 537 | } | 554 | } |
72 | 538 | 555 | ||
78 | 539 | #if 0 | 556 | /** Structure to track the data needed for upstart events. This cleans |
79 | 540 | void | 557 | up the lifecycle as we're passing this as a pointer through the |
80 | 541 | Registry::Impl::setManager (Registry::Manager* manager) | 558 | GLib calls. */ |
81 | 542 | { | 559 | struct upstartEventData |
82 | 543 | if (_manager != nullptr) | 560 | { |
83 | 561 | /** Keeping a weak pointer because the handle is held by | ||
84 | 562 | the registry implementation. */ | ||
85 | 563 | std::weak_ptr<Registry> weakReg; | ||
86 | 564 | }; | ||
87 | 565 | |||
88 | 566 | /** Take the GVariant of parameters and turn them into an application and | ||
89 | 567 | and instance. Easier to read in the smaller function */ | ||
90 | 568 | std::tuple<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> Registry::Impl::managerParams( | ||
91 | 569 | const std::shared_ptr<GVariant>& params, const std::shared_ptr<Registry>& reg) | ||
92 | 570 | { | ||
93 | 571 | std::shared_ptr<Application> app; | ||
94 | 572 | std::shared_ptr<Application::Instance> instance; | ||
95 | 573 | |||
96 | 574 | const gchar* cappid = nullptr; | ||
97 | 575 | g_variant_get(params.get(), "(&s)", &cappid); | ||
98 | 576 | |||
99 | 577 | auto appid = ubuntu::app_launch::AppID::find(reg, cappid); | ||
100 | 578 | app = ubuntu::app_launch::Application::create(appid, reg); | ||
101 | 579 | |||
102 | 580 | return std::make_tuple(app, instance); | ||
103 | 581 | } | ||
104 | 582 | |||
105 | 583 | /** Used to store data for manager based signal handlers. Has a link to the | ||
106 | 584 | registry and the callback to use in a C++ style. */ | ||
107 | 585 | struct managerEventData | ||
108 | 586 | { | ||
109 | 587 | /* Keeping a weak pointer because the handle is held by | ||
110 | 588 | the registry implementation. */ | ||
111 | 589 | std::weak_ptr<Registry> weakReg; | ||
112 | 590 | std::function<void(const std::shared_ptr<Registry>& reg, | ||
113 | 591 | const std::shared_ptr<Application>& app, | ||
114 | 592 | const std::shared_ptr<Application::Instance>& instance, | ||
115 | 593 | const std::shared_ptr<GDBusConnection>&, | ||
116 | 594 | const std::string&, | ||
117 | 595 | const std::shared_ptr<GVariant>&)> | ||
118 | 596 | func; | ||
119 | 597 | }; | ||
120 | 598 | |||
121 | 599 | /** Register for a signal for the manager. All of the signals needed this same | ||
122 | 600 | code so it got pulled out into a function. Takes the same of the signal, the registry | ||
123 | 601 | that we're using and a function to call after we've messaged all the parameters | ||
124 | 602 | into being something C++-ish. */ | ||
125 | 603 | guint Registry::Impl::managerSignalHelper(const std::shared_ptr<Registry>& reg, | ||
126 | 604 | const std::string& signalname, | ||
127 | 605 | std::function<void(const std::shared_ptr<Registry>& reg, | ||
128 | 606 | const std::shared_ptr<Application>& app, | ||
129 | 607 | const std::shared_ptr<Application::Instance>& instance, | ||
130 | 608 | const std::shared_ptr<GDBusConnection>&, | ||
131 | 609 | const std::string&, | ||
132 | 610 | const std::shared_ptr<GVariant>&)> responsefunc) | ||
133 | 611 | { | ||
134 | 612 | managerEventData* focusdata = new managerEventData{reg, responsefunc}; | ||
135 | 613 | |||
136 | 614 | return g_dbus_connection_signal_subscribe( | ||
137 | 615 | reg->impl->_dbus.get(), /* bus */ | ||
138 | 616 | nullptr, /* sender */ | ||
139 | 617 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
140 | 618 | signalname.c_str(), /* signal */ | ||
141 | 619 | "/", /* path */ | ||
142 | 620 | nullptr, /* arg0 */ | ||
143 | 621 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
144 | 622 | [](GDBusConnection* cconn, const gchar* csender, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
145 | 623 | gpointer user_data) -> void { | ||
146 | 624 | auto data = reinterpret_cast<managerEventData*>(user_data); | ||
147 | 625 | auto reg = data->weakReg.lock(); | ||
148 | 626 | |||
149 | 627 | /* If we're still conneted and the manager has been cleared | ||
150 | 628 | we'll just be a no-op */ | ||
151 | 629 | if (!reg->impl->manager_) | ||
152 | 630 | { | ||
153 | 631 | return; | ||
154 | 632 | } | ||
155 | 633 | |||
156 | 634 | auto vparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); | ||
157 | 635 | auto conn = std::shared_ptr<GDBusConnection>(reinterpret_cast<GDBusConnection*>(g_object_ref(cconn)), | ||
158 | 636 | [](GDBusConnection* con) { g_clear_object(&con); }); | ||
159 | 637 | std::string sender = csender; | ||
160 | 638 | std::shared_ptr<Application> app; | ||
161 | 639 | std::shared_ptr<Application::Instance> instance; | ||
162 | 640 | |||
163 | 641 | std::tie(app, instance) = managerParams(vparams, reg); | ||
164 | 642 | |||
165 | 643 | data->func(reg, app, instance, conn, sender, vparams); | ||
166 | 644 | }, | ||
167 | 645 | focusdata, | ||
168 | 646 | [](gpointer user_data) { | ||
169 | 647 | auto data = reinterpret_cast<managerEventData*>(user_data); | ||
170 | 648 | delete data; | ||
171 | 649 | }); /* user data destroy */ | ||
172 | 650 | } | ||
173 | 651 | |||
174 | 652 | /** Set the manager for the registry. This includes tracking the pointer | ||
175 | 653 | as well as setting up the signals to call back into the manager. The | ||
176 | 654 | signals are only setup once per registry even if the manager is cleared | ||
177 | 655 | and changed again. They will just be no-op's in those cases. | ||
178 | 656 | */ | ||
179 | 657 | void Registry::Impl::setManager(std::shared_ptr<Registry::Manager> manager, std::shared_ptr<Registry> reg) | ||
180 | 658 | { | ||
181 | 659 | if (reg->impl->manager_) | ||
182 | 544 | { | 660 | { |
183 | 545 | throw std::runtime_error("Already have a manager and trying to set another"); | 661 | throw std::runtime_error("Already have a manager and trying to set another"); |
184 | 546 | } | 662 | } |
185 | 547 | 663 | ||
187 | 548 | _manager = manager; | 664 | g_debug("Setting a new manager"); |
188 | 665 | reg->impl->manager_ = manager; | ||
189 | 666 | |||
190 | 667 | std::call_once(reg->impl->flag_managerSignals, [reg]() { | ||
191 | 668 | if (!reg->impl->thread.executeOnThread<bool>([reg]() { | ||
192 | 669 | reg->impl->handle_managerSignalFocus = managerSignalHelper( | ||
193 | 670 | reg, "UnityFocusRequest", | ||
194 | 671 | [](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app, | ||
195 | 672 | const std::shared_ptr<Application::Instance>& instance, | ||
196 | 673 | const std::shared_ptr<GDBusConnection>& conn, const std::string& sender, | ||
197 | 674 | const std::shared_ptr<GVariant>& params) { | ||
198 | 675 | /* Nothing to do today */ | ||
199 | 676 | reg->impl->manager_->focusRequest(app, instance, [](bool response) { | ||
200 | 677 | /* NOTE: We have no clue what thread this is gonna be | ||
201 | 678 | executed on, but since we're just talking to the GDBus | ||
202 | 679 | thread it isn't an issue today. Be careful in changing | ||
203 | 680 | this code. */ | ||
204 | 681 | }); | ||
205 | 682 | }); | ||
206 | 683 | reg->impl->handle_managerSignalStarting = managerSignalHelper( | ||
207 | 684 | reg, "UnityStartingBroadcast", | ||
208 | 685 | [](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app, | ||
209 | 686 | const std::shared_ptr<Application::Instance>& instance, | ||
210 | 687 | const std::shared_ptr<GDBusConnection>& conn, const std::string& sender, | ||
211 | 688 | const std::shared_ptr<GVariant>& params) { | ||
212 | 689 | |||
213 | 690 | reg->impl->manager_->startingRequest(app, instance, [conn, sender, params](bool response) { | ||
214 | 691 | /* NOTE: We have no clue what thread this is gonna be | ||
215 | 692 | executed on, but since we're just talking to the GDBus | ||
216 | 693 | thread it isn't an issue today. Be careful in changing | ||
217 | 694 | this code. */ | ||
218 | 695 | if (response) | ||
219 | 696 | { | ||
220 | 697 | g_dbus_connection_emit_signal(conn.get(), sender.c_str(), /* destination */ | ||
221 | 698 | "/", /* path */ | ||
222 | 699 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
223 | 700 | "UnityStartingSignal", /* signal */ | ||
224 | 701 | params.get(), /* params, the same */ | ||
225 | 702 | nullptr); /* error */ | ||
226 | 703 | } | ||
227 | 704 | }); | ||
228 | 705 | }); | ||
229 | 706 | reg->impl->handle_managerSignalResume = managerSignalHelper( | ||
230 | 707 | reg, "UnityResumeRequest", | ||
231 | 708 | [](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app, | ||
232 | 709 | const std::shared_ptr<Application::Instance>& instance, | ||
233 | 710 | const std::shared_ptr<GDBusConnection>& conn, const std::string& sender, | ||
234 | 711 | const std::shared_ptr<GVariant>& params) { | ||
235 | 712 | reg->impl->manager_->resumeRequest(app, instance, [conn, sender, params](bool response) { | ||
236 | 713 | /* NOTE: We have no clue what thread this is gonna be | ||
237 | 714 | executed on, but since we're just talking to the GDBus | ||
238 | 715 | thread it isn't an issue today. Be careful in changing | ||
239 | 716 | this code. */ | ||
240 | 717 | if (response) | ||
241 | 718 | { | ||
242 | 719 | g_dbus_connection_emit_signal(conn.get(), sender.c_str(), /* destination */ | ||
243 | 720 | "/", /* path */ | ||
244 | 721 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
245 | 722 | "UnityResumeResponse", /* signal */ | ||
246 | 723 | params.get(), /* params, the same */ | ||
247 | 724 | nullptr); /* error */ | ||
248 | 725 | } | ||
249 | 726 | }); | ||
250 | 727 | }); | ||
251 | 728 | |||
252 | 729 | return true; | ||
253 | 730 | })) | ||
254 | 731 | { | ||
255 | 732 | g_warning("Unable to install manager signals"); | ||
256 | 733 | } | ||
257 | 734 | }); | ||
258 | 549 | } | 735 | } |
259 | 550 | 736 | ||
262 | 551 | void | 737 | /** Clear the manager pointer */ |
263 | 552 | Registry::Impl::clearManager () | 738 | void Registry::Impl::clearManager() |
264 | 553 | { | 739 | { |
266 | 554 | _manager = nullptr; | 740 | g_debug("Clearing the manager"); |
267 | 741 | manager_.reset(); | ||
268 | 555 | } | 742 | } |
269 | 556 | #endif | ||
270 | 557 | 743 | ||
271 | 558 | /** App start watching, if we're registered for the signal we | 744 | /** App start watching, if we're registered for the signal we |
272 | 559 | can't wait on it. We are making this static right now because | 745 | can't wait on it. We are making this static right now because |
273 | @@ -576,5 +762,301 @@ | |||
274 | 576 | return watchingAppStarting_; | 762 | return watchingAppStarting_; |
275 | 577 | } | 763 | } |
276 | 578 | 764 | ||
277 | 765 | /** Regex to parse the JOB environment variable from Upstart */ | ||
278 | 766 | std::regex jobenv_regex{"^JOB=(application\\-(?:click|snap|legacy))$"}; | ||
279 | 767 | /** Regex to parse the INSTANCE environment variable from Upstart */ | ||
280 | 768 | std::regex instanceenv_regex{"^INSTANCE=(.*?)(?:\\-([0-9]*))?+$"}; | ||
281 | 769 | |||
282 | 770 | /** Core of most of the events that come from Upstart directly. Includes parsing of the | ||
283 | 771 | Upstart event environment and calling the appropriate signal with the right Application | ||
284 | 772 | object and eventually its instance */ | ||
285 | 773 | void Registry::Impl::upstartEventEmitted( | ||
286 | 774 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>>& signal, | ||
287 | 775 | std::shared_ptr<GVariant> params, | ||
288 | 776 | const std::shared_ptr<Registry>& reg) | ||
289 | 777 | { | ||
290 | 778 | std::string jobname; | ||
291 | 779 | std::string sappid; | ||
292 | 780 | std::string instance; | ||
293 | 781 | |||
294 | 782 | gchar* env = nullptr; | ||
295 | 783 | GVariant* envs = g_variant_get_child_value(params.get(), 1); | ||
296 | 784 | GVariantIter iter; | ||
297 | 785 | g_variant_iter_init(&iter, envs); | ||
298 | 786 | |||
299 | 787 | while (g_variant_iter_loop(&iter, "s", &env)) | ||
300 | 788 | { | ||
301 | 789 | std::smatch match; | ||
302 | 790 | std::string senv = env; | ||
303 | 791 | |||
304 | 792 | if (std::regex_match(senv, match, jobenv_regex)) | ||
305 | 793 | { | ||
306 | 794 | jobname = match[1].str(); | ||
307 | 795 | } | ||
308 | 796 | else if (std::regex_match(senv, match, instanceenv_regex)) | ||
309 | 797 | { | ||
310 | 798 | sappid = match[1].str(); | ||
311 | 799 | instance = match[2].str(); | ||
312 | 800 | } | ||
313 | 801 | } | ||
314 | 802 | |||
315 | 803 | g_variant_unref(envs); | ||
316 | 804 | |||
317 | 805 | if (jobname.empty()) | ||
318 | 806 | { | ||
319 | 807 | return; | ||
320 | 808 | } | ||
321 | 809 | |||
322 | 810 | g_debug("Upstart Event for job '%s' appid '%s' instance '%s'", jobname.c_str(), sappid.c_str(), instance.c_str()); | ||
323 | 811 | |||
324 | 812 | auto appid = AppID::find(reg, sappid); | ||
325 | 813 | auto app = Application::create(appid, reg); | ||
326 | 814 | |||
327 | 815 | // TODO: Figure otu creating instances | ||
328 | 816 | |||
329 | 817 | signal(app, {}); | ||
330 | 818 | } | ||
331 | 819 | |||
332 | 820 | /** Grab the signal object for application startup. If we're not already listing for | ||
333 | 821 | those signals this sets up a listener for them. */ | ||
334 | 822 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>>& Registry::Impl::appStarted( | ||
335 | 823 | const std::shared_ptr<Registry>& reg) | ||
336 | 824 | { | ||
337 | 825 | std::call_once(flag_appStarted, [reg]() { | ||
338 | 826 | reg->impl->thread.executeOnThread<bool>([reg]() { | ||
339 | 827 | upstartEventData* data = new upstartEventData{reg}; | ||
340 | 828 | |||
341 | 829 | reg->impl->handle_appStarted = g_dbus_connection_signal_subscribe( | ||
342 | 830 | reg->impl->_dbus.get(), /* bus */ | ||
343 | 831 | nullptr, /* sender */ | ||
344 | 832 | DBUS_INTERFACE_UPSTART, /* interface */ | ||
345 | 833 | "EventEmitted", /* signal */ | ||
346 | 834 | DBUS_PATH_UPSTART, /* path */ | ||
347 | 835 | "started", /* arg0 */ | ||
348 | 836 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
349 | 837 | [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
350 | 838 | gpointer user_data) -> void { | ||
351 | 839 | auto data = reinterpret_cast<upstartEventData*>(user_data); | ||
352 | 840 | auto reg = data->weakReg.lock(); | ||
353 | 841 | auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); | ||
354 | 842 | reg->impl->upstartEventEmitted(reg->impl->sig_appStarted, sparams, reg); | ||
355 | 843 | }, /* callback */ | ||
356 | 844 | data, /* user data */ | ||
357 | 845 | [](gpointer user_data) { | ||
358 | 846 | auto data = reinterpret_cast<upstartEventData*>(user_data); | ||
359 | 847 | delete data; | ||
360 | 848 | }); /* user data destroy */ | ||
361 | 849 | |||
362 | 850 | return true; | ||
363 | 851 | }); | ||
364 | 852 | }); | ||
365 | 853 | |||
366 | 854 | return sig_appStarted; | ||
367 | 855 | } | ||
368 | 856 | |||
369 | 857 | /** Grab the signal object for application stopping. If we're not already listing for | ||
370 | 858 | those signals this sets up a listener for them. */ | ||
371 | 859 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>>& Registry::Impl::appStopped( | ||
372 | 860 | const std::shared_ptr<Registry>& reg) | ||
373 | 861 | { | ||
374 | 862 | std::call_once(flag_appStopped, [reg]() { | ||
375 | 863 | reg->impl->thread.executeOnThread<bool>([reg]() { | ||
376 | 864 | upstartEventData* data = new upstartEventData{reg}; | ||
377 | 865 | |||
378 | 866 | reg->impl->handle_appStopped = g_dbus_connection_signal_subscribe( | ||
379 | 867 | reg->impl->_dbus.get(), /* bus */ | ||
380 | 868 | nullptr, /* sender */ | ||
381 | 869 | DBUS_INTERFACE_UPSTART, /* interface */ | ||
382 | 870 | "EventEmitted", /* signal */ | ||
383 | 871 | DBUS_PATH_UPSTART, /* path */ | ||
384 | 872 | "stopped", /* arg0 */ | ||
385 | 873 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
386 | 874 | [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
387 | 875 | gpointer user_data) -> void { | ||
388 | 876 | auto data = reinterpret_cast<upstartEventData*>(user_data); | ||
389 | 877 | auto reg = data->weakReg.lock(); | ||
390 | 878 | auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); | ||
391 | 879 | reg->impl->upstartEventEmitted(reg->impl->sig_appStopped, sparams, reg); | ||
392 | 880 | }, /* callback */ | ||
393 | 881 | data, /* user data */ | ||
394 | 882 | [](gpointer user_data) { | ||
395 | 883 | auto data = reinterpret_cast<upstartEventData*>(user_data); | ||
396 | 884 | delete data; | ||
397 | 885 | }); /* user data destroy */ | ||
398 | 886 | |||
399 | 887 | return true; | ||
400 | 888 | }); | ||
401 | 889 | }); | ||
402 | 890 | |||
403 | 891 | return sig_appStopped; | ||
404 | 892 | } | ||
405 | 893 | |||
406 | 894 | /** Grab the signal object for application failing. If we're not already listing for | ||
407 | 895 | those signals this sets up a listener for them. */ | ||
408 | 896 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, Registry::FailureType>& | ||
409 | 897 | Registry::Impl::appFailed(const std::shared_ptr<Registry>& reg) | ||
410 | 898 | { | ||
411 | 899 | std::call_once(flag_appFailed, [reg]() { | ||
412 | 900 | reg->impl->thread.executeOnThread<bool>([reg]() { | ||
413 | 901 | upstartEventData* data = new upstartEventData{reg}; | ||
414 | 902 | |||
415 | 903 | reg->impl->handle_appFailed = g_dbus_connection_signal_subscribe( | ||
416 | 904 | reg->impl->_dbus.get(), /* bus */ | ||
417 | 905 | nullptr, /* sender */ | ||
418 | 906 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
419 | 907 | "ApplicationFailed", /* signal */ | ||
420 | 908 | "/", /* path */ | ||
421 | 909 | nullptr, /* arg0 */ | ||
422 | 910 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
423 | 911 | [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
424 | 912 | gpointer user_data) -> void { | ||
425 | 913 | auto data = reinterpret_cast<upstartEventData*>(user_data); | ||
426 | 914 | auto reg = data->weakReg.lock(); | ||
427 | 915 | |||
428 | 916 | const gchar* sappid = NULL; | ||
429 | 917 | const gchar* typestr = NULL; | ||
430 | 918 | |||
431 | 919 | Registry::FailureType type = Registry::FailureType::CRASH; | ||
432 | 920 | g_variant_get(params, "(&s&s)", &sappid, &typestr); | ||
433 | 921 | |||
434 | 922 | if (g_strcmp0("crash", typestr) == 0) | ||
435 | 923 | { | ||
436 | 924 | type = Registry::FailureType::CRASH; | ||
437 | 925 | } | ||
438 | 926 | else if (g_strcmp0("start-failure", typestr) == 0) | ||
439 | 927 | { | ||
440 | 928 | type = Registry::FailureType::START_FAILURE; | ||
441 | 929 | } | ||
442 | 930 | else | ||
443 | 931 | { | ||
444 | 932 | g_warning("Application failure type '%s' unknown, reporting as a crash", typestr); | ||
445 | 933 | } | ||
446 | 934 | |||
447 | 935 | auto appid = AppID::find(reg, sappid); | ||
448 | 936 | auto app = Application::create(appid, reg); | ||
449 | 937 | |||
450 | 938 | /* TODO: Instance issues */ | ||
451 | 939 | |||
452 | 940 | reg->impl->sig_appFailed(app, {}, type); | ||
453 | 941 | }, /* callback */ | ||
454 | 942 | data, /* user data */ | ||
455 | 943 | [](gpointer user_data) { | ||
456 | 944 | auto data = reinterpret_cast<upstartEventData*>(user_data); | ||
457 | 945 | delete data; | ||
458 | 946 | }); /* user data destroy */ | ||
459 | 947 | |||
460 | 948 | return true; | ||
461 | 949 | }); | ||
462 | 950 | }); | ||
463 | 951 | |||
464 | 952 | return sig_appFailed; | ||
465 | 953 | } | ||
466 | 954 | |||
467 | 955 | /** Core handler for pause and resume events. Includes turning the GVariant | ||
468 | 956 | pid list into a std::vector and getting the application object. */ | ||
469 | 957 | void Registry::Impl::pauseEventEmitted( | ||
470 | 958 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&>& signal, | ||
471 | 959 | const std::shared_ptr<GVariant>& params, | ||
472 | 960 | const std::shared_ptr<Registry>& reg) | ||
473 | 961 | { | ||
474 | 962 | std::vector<pid_t> pids; | ||
475 | 963 | GVariant* vappid = g_variant_get_child_value(params.get(), 0); | ||
476 | 964 | GVariant* vpids = g_variant_get_child_value(params.get(), 1); | ||
477 | 965 | guint64 pid; | ||
478 | 966 | GVariantIter thispid; | ||
479 | 967 | g_variant_iter_init(&thispid, vpids); | ||
480 | 968 | |||
481 | 969 | while (g_variant_iter_loop(&thispid, "t", &pid)) | ||
482 | 970 | { | ||
483 | 971 | pids.emplace_back(pid); | ||
484 | 972 | } | ||
485 | 973 | |||
486 | 974 | auto cappid = g_variant_get_string(vappid, NULL); | ||
487 | 975 | auto appid = ubuntu::app_launch::AppID::find(reg, cappid); | ||
488 | 976 | auto app = Application::create(appid, reg); | ||
489 | 977 | |||
490 | 978 | /* TODO: Instance */ | ||
491 | 979 | signal(app, {}, pids); | ||
492 | 980 | |||
493 | 981 | g_variant_unref(vappid); | ||
494 | 982 | g_variant_unref(vpids); | ||
495 | 983 | |||
496 | 984 | return; | ||
497 | 985 | } | ||
498 | 986 | |||
499 | 987 | /** Grab the signal object for application paused. If we're not already listing for | ||
500 | 988 | those signals this sets up a listener for them. */ | ||
501 | 989 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&>& | ||
502 | 990 | Registry::Impl::appPaused(const std::shared_ptr<Registry>& reg) | ||
503 | 991 | { | ||
504 | 992 | std::call_once(flag_appPaused, [&]() { | ||
505 | 993 | reg->impl->thread.executeOnThread<bool>([reg]() { | ||
506 | 994 | upstartEventData* data = new upstartEventData{reg}; | ||
507 | 995 | |||
508 | 996 | reg->impl->handle_appPaused = g_dbus_connection_signal_subscribe( | ||
509 | 997 | reg->impl->_dbus.get(), /* bus */ | ||
510 | 998 | nullptr, /* sender */ | ||
511 | 999 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
512 | 1000 | "ApplicationPaused", /* signal */ | ||
513 | 1001 | "/", /* path */ | ||
514 | 1002 | nullptr, /* arg0 */ | ||
515 | 1003 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
516 | 1004 | [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
517 | 1005 | gpointer user_data) -> void { | ||
518 | 1006 | auto data = reinterpret_cast<upstartEventData*>(user_data); | ||
519 | 1007 | auto reg = data->weakReg.lock(); | ||
520 | 1008 | auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); | ||
521 | 1009 | reg->impl->pauseEventEmitted(reg->impl->sig_appPaused, sparams, reg); | ||
522 | 1010 | }, /* callback */ | ||
523 | 1011 | data, /* user data */ | ||
524 | 1012 | [](gpointer user_data) { | ||
525 | 1013 | auto data = reinterpret_cast<upstartEventData*>(user_data); | ||
526 | 1014 | delete data; | ||
527 | 1015 | }); /* user data destroy */ | ||
528 | 1016 | |||
529 | 1017 | return true; | ||
530 | 1018 | }); | ||
531 | 1019 | }); | ||
532 | 1020 | |||
533 | 1021 | return sig_appPaused; | ||
534 | 1022 | } | ||
535 | 1023 | |||
536 | 1024 | /** Grab the signal object for application resumed. If we're not already listing for | ||
537 | 1025 | those signals this sets up a listener for them. */ | ||
538 | 1026 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&>& | ||
539 | 1027 | Registry::Impl::appResumed(const std::shared_ptr<Registry>& reg) | ||
540 | 1028 | { | ||
541 | 1029 | std::call_once(flag_appResumed, [&]() { | ||
542 | 1030 | reg->impl->thread.executeOnThread<bool>([reg]() { | ||
543 | 1031 | upstartEventData* data = new upstartEventData{reg}; | ||
544 | 1032 | |||
545 | 1033 | reg->impl->handle_appResumed = g_dbus_connection_signal_subscribe( | ||
546 | 1034 | reg->impl->_dbus.get(), /* bus */ | ||
547 | 1035 | nullptr, /* sender */ | ||
548 | 1036 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
549 | 1037 | "ApplicationResumed", /* signal */ | ||
550 | 1038 | "/", /* path */ | ||
551 | 1039 | nullptr, /* arg0 */ | ||
552 | 1040 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
553 | 1041 | [](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params, | ||
554 | 1042 | gpointer user_data) -> void { | ||
555 | 1043 | auto data = reinterpret_cast<upstartEventData*>(user_data); | ||
556 | 1044 | auto reg = data->weakReg.lock(); | ||
557 | 1045 | auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref); | ||
558 | 1046 | reg->impl->pauseEventEmitted(reg->impl->sig_appResumed, sparams, reg); | ||
559 | 1047 | }, /* callback */ | ||
560 | 1048 | data, /* user data */ | ||
561 | 1049 | [](gpointer user_data) { | ||
562 | 1050 | auto data = reinterpret_cast<upstartEventData*>(user_data); | ||
563 | 1051 | delete data; | ||
564 | 1052 | }); /* user data destroy */ | ||
565 | 1053 | |||
566 | 1054 | return true; | ||
567 | 1055 | }); | ||
568 | 1056 | }); | ||
569 | 1057 | |||
570 | 1058 | return sig_appResumed; | ||
571 | 1059 | } | ||
572 | 1060 | |||
573 | 579 | } // namespace app_launch | 1061 | } // namespace app_launch |
574 | 580 | } // namespace ubuntu | 1062 | } // namespace ubuntu |
575 | 581 | 1063 | ||
576 | === modified file 'libubuntu-app-launch/registry-impl.h' | |||
577 | --- libubuntu-app-launch/registry-impl.h 2016-09-23 22:30:51 +0000 | |||
578 | +++ libubuntu-app-launch/registry-impl.h 2016-11-07 20:56:13 +0000 | |||
579 | @@ -53,10 +53,8 @@ | |||
580 | 53 | std::list<AppID::Package> getClickPackages(); | 53 | std::list<AppID::Package> getClickPackages(); |
581 | 54 | std::string getClickDir(const std::string& package); | 54 | std::string getClickDir(const std::string& package); |
582 | 55 | 55 | ||
587 | 56 | #if 0 | 56 | static void setManager(std::shared_ptr<Registry::Manager> manager, std::shared_ptr<Registry> registry); |
588 | 57 | void setManager (Registry::Manager* manager); | 57 | void clearManager(); |
585 | 58 | void clearManager (); | ||
586 | 59 | #endif | ||
589 | 60 | 58 | ||
590 | 61 | /** Shared context thread for events and background tasks | 59 | /** Shared context thread for events and background tasks |
591 | 62 | that UAL subtasks are doing */ | 60 | that UAL subtasks are doing */ |
592 | @@ -82,6 +80,18 @@ | |||
593 | 82 | static std::string printJson(std::shared_ptr<JsonObject> jsonobj); | 80 | static std::string printJson(std::shared_ptr<JsonObject> jsonobj); |
594 | 83 | static std::string printJson(std::shared_ptr<JsonNode> jsonnode); | 81 | static std::string printJson(std::shared_ptr<JsonNode> jsonnode); |
595 | 84 | 82 | ||
596 | 83 | /* Signals to discover what is happening to apps */ | ||
597 | 84 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>>& appStarted( | ||
598 | 85 | const std::shared_ptr<Registry>& reg); | ||
599 | 86 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>>& appStopped( | ||
600 | 87 | const std::shared_ptr<Registry>& reg); | ||
601 | 88 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, FailureType>& appFailed( | ||
602 | 89 | const std::shared_ptr<Registry>& reg); | ||
603 | 90 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&>& appPaused( | ||
604 | 91 | const std::shared_ptr<Registry>& reg); | ||
605 | 92 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&>& appResumed( | ||
606 | 93 | const std::shared_ptr<Registry>& reg); | ||
607 | 94 | |||
608 | 85 | /* Signal Hints */ | 95 | /* Signal Hints */ |
609 | 86 | /* NOTE: Static because we don't have registry instances in the C | 96 | /* NOTE: Static because we don't have registry instances in the C |
610 | 87 | code right now. We want these to not be static in the future */ | 97 | code right now. We want these to not be static in the future */ |
611 | @@ -89,22 +99,77 @@ | |||
612 | 89 | static bool isWatchingAppStarting(); | 99 | static bool isWatchingAppStarting(); |
613 | 90 | 100 | ||
614 | 91 | private: | 101 | private: |
622 | 92 | Registry* _registry; | 102 | Registry* _registry; /**< The Registry that we're spawned from */ |
623 | 93 | #if 0 | 103 | std::shared_ptr<Registry::Manager> manager_; /**< Application manager if registered */ |
624 | 94 | Registry::Manager* _manager; | 104 | |
625 | 95 | #endif | 105 | std::shared_ptr<ClickDB> _clickDB; /**< Shared instance of the Click Database */ |
626 | 96 | 106 | std::shared_ptr<ClickUser> _clickUser; /**< Click database filtered by the current user */ | |
627 | 97 | std::shared_ptr<ClickDB> _clickDB; | 107 | |
628 | 98 | std::shared_ptr<ClickUser> _clickUser; | 108 | /** Signal object for applications started */ |
629 | 109 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> sig_appStarted; | ||
630 | 110 | /** Signal object for applications stopped */ | ||
631 | 111 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> sig_appStopped; | ||
632 | 112 | /** Signal object for applications failed */ | ||
633 | 113 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, FailureType> sig_appFailed; | ||
634 | 114 | /** Signal object for applications paused */ | ||
635 | 115 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&> | ||
636 | 116 | sig_appPaused; | ||
637 | 117 | /** Signal object for applications resumed */ | ||
638 | 118 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&> | ||
639 | 119 | sig_appResumed; | ||
640 | 120 | |||
641 | 121 | guint handle_appStarted{0}; /**< GDBus signal watcher handle for app started signal */ | ||
642 | 122 | guint handle_appStopped{0}; /**< GDBus signal watcher handle for app stopped signal */ | ||
643 | 123 | guint handle_appFailed{0}; /**< GDBus signal watcher handle for app failed signal */ | ||
644 | 124 | guint handle_appPaused{0}; /**< GDBus signal watcher handle for app paused signal */ | ||
645 | 125 | guint handle_appResumed{0}; /**< GDBus signal watcher handle for app resumed signal */ | ||
646 | 126 | guint handle_managerSignalFocus{0}; /**< GDBus signal watcher handle for app focused signal */ | ||
647 | 127 | guint handle_managerSignalResume{0}; /**< GDBus signal watcher handle for app resumed signal */ | ||
648 | 128 | guint handle_managerSignalStarting{0}; /**< GDBus signal watcher handle for app starting signal */ | ||
649 | 129 | |||
650 | 130 | std::once_flag flag_appStarted; /**< Variable to track to see if signal handlers are installed for application | ||
651 | 131 | started */ | ||
652 | 132 | std::once_flag flag_appStopped; /**< Variable to track to see if signal handlers are installed for application | ||
653 | 133 | stopped */ | ||
654 | 134 | std::once_flag | ||
655 | 135 | flag_appFailed; /**< Variable to track to see if signal handlers are installed for application failed */ | ||
656 | 136 | std::once_flag | ||
657 | 137 | flag_appPaused; /**< Variable to track to see if signal handlers are installed for application paused */ | ||
658 | 138 | std::once_flag flag_appResumed; /**< Variable to track to see if signal handlers are installed for application | ||
659 | 139 | resumed */ | ||
660 | 140 | std::once_flag flag_managerSignals; /**< Variable to track to see if signal handlers are installed for the manager | ||
661 | 141 | signals of focused, resumed and starting */ | ||
662 | 142 | |||
663 | 143 | void upstartEventEmitted(core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>>& signal, | ||
664 | 144 | std::shared_ptr<GVariant> params, | ||
665 | 145 | const std::shared_ptr<Registry>& reg); | ||
666 | 146 | void pauseEventEmitted( | ||
667 | 147 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&>& signal, | ||
668 | 148 | const std::shared_ptr<GVariant>& params, | ||
669 | 149 | const std::shared_ptr<Registry>& reg); | ||
670 | 150 | static std::tuple<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> managerParams( | ||
671 | 151 | const std::shared_ptr<GVariant>& params, const std::shared_ptr<Registry>& reg); | ||
672 | 152 | static guint managerSignalHelper(const std::shared_ptr<Registry>& reg, | ||
673 | 153 | const std::string& signalname, | ||
674 | 154 | std::function<void(const std::shared_ptr<Registry>& reg, | ||
675 | 155 | const std::shared_ptr<Application>& app, | ||
676 | 156 | const std::shared_ptr<Application::Instance>& instance, | ||
677 | 157 | const std::shared_ptr<GDBusConnection>&, | ||
678 | 158 | const std::string&, | ||
679 | 159 | const std::shared_ptr<GVariant>&)> responsefunc); | ||
680 | 99 | 160 | ||
681 | 100 | void initClick(); | 161 | void initClick(); |
682 | 101 | 162 | ||
683 | 163 | /** Shared instance of the Zeitgeist Log */ | ||
684 | 102 | std::shared_ptr<ZeitgeistLog> zgLog_; | 164 | std::shared_ptr<ZeitgeistLog> zgLog_; |
685 | 103 | 165 | ||
686 | 166 | /** Shared connection to CGManager */ | ||
687 | 104 | std::shared_ptr<GDBusConnection> cgManager_; | 167 | std::shared_ptr<GDBusConnection> cgManager_; |
688 | 105 | 168 | ||
689 | 106 | void initCGManager(); | 169 | void initCGManager(); |
690 | 107 | 170 | ||
691 | 171 | /** All of our icon finders based on the path that they're looking | ||
692 | 172 | into */ | ||
693 | 108 | std::unordered_map<std::string, std::shared_ptr<IconFinder>> _iconFinders; | 173 | std::unordered_map<std::string, std::shared_ptr<IconFinder>> _iconFinders; |
694 | 109 | 174 | ||
695 | 110 | /** Getting the Upstart job path is relatively expensive in | 175 | /** Getting the Upstart job path is relatively expensive in |
696 | 111 | 176 | ||
697 | === modified file 'libubuntu-app-launch/registry.cpp' | |||
698 | --- libubuntu-app-launch/registry.cpp 2016-08-26 17:33:34 +0000 | |||
699 | +++ libubuntu-app-launch/registry.cpp 2016-11-07 20:56:13 +0000 | |||
700 | @@ -57,7 +57,7 @@ | |||
701 | 57 | instances.splice(instances.begin(), connection->impl->upstartInstancesForJob("application-snap")); | 57 | instances.splice(instances.begin(), connection->impl->upstartInstancesForJob("application-snap")); |
702 | 58 | 58 | ||
703 | 59 | /* Remove the instance ID */ | 59 | /* Remove the instance ID */ |
705 | 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 { |
706 | 61 | static const std::regex instanceregex("^(.*)-[0-9]*$"); | 61 | static const std::regex instanceregex("^(.*)-[0-9]*$"); |
707 | 62 | std::smatch match; | 62 | std::smatch match; |
708 | 63 | if (std::regex_match(instancename, match, instanceregex)) | 63 | if (std::regex_match(instancename, match, instanceregex)) |
709 | @@ -87,7 +87,7 @@ | |||
710 | 87 | 87 | ||
711 | 88 | g_debug("Overall there are %d instances: %s", int(instanceset.size()), | 88 | g_debug("Overall there are %d instances: %s", int(instanceset.size()), |
712 | 89 | std::accumulate(instanceset.begin(), instanceset.end(), std::string{}, | 89 | std::accumulate(instanceset.begin(), instanceset.end(), std::string{}, |
714 | 90 | [](const std::string &instr, std::string instance) { | 90 | [](const std::string& instr, std::string instance) { |
715 | 91 | return instr.empty() ? instance : instr + ", " + instance; | 91 | return instr.empty() ? instance : instr + ", " + instance; |
716 | 92 | }) | 92 | }) |
717 | 93 | .c_str()); | 93 | .c_str()); |
718 | @@ -127,6 +127,16 @@ | |||
719 | 127 | return list; | 127 | return list; |
720 | 128 | } | 128 | } |
721 | 129 | 129 | ||
722 | 130 | void Registry::setManager(std::shared_ptr<Manager> manager, std::shared_ptr<Registry> registry) | ||
723 | 131 | { | ||
724 | 132 | Registry::Impl::setManager(manager, registry); | ||
725 | 133 | } | ||
726 | 134 | |||
727 | 135 | void Registry::clearManager() | ||
728 | 136 | { | ||
729 | 137 | impl->clearManager(); | ||
730 | 138 | } | ||
731 | 139 | |||
732 | 130 | std::shared_ptr<Registry> defaultRegistry; | 140 | std::shared_ptr<Registry> defaultRegistry; |
733 | 131 | std::shared_ptr<Registry> Registry::getDefault() | 141 | std::shared_ptr<Registry> Registry::getDefault() |
734 | 132 | { | 142 | { |
735 | @@ -143,5 +153,35 @@ | |||
736 | 143 | defaultRegistry.reset(); | 153 | defaultRegistry.reset(); |
737 | 144 | } | 154 | } |
738 | 145 | 155 | ||
739 | 156 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>>& Registry::appStarted( | ||
740 | 157 | const std::shared_ptr<Registry>& reg) | ||
741 | 158 | { | ||
742 | 159 | return reg->impl->appStarted(reg); | ||
743 | 160 | } | ||
744 | 161 | |||
745 | 162 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>>& Registry::appStopped( | ||
746 | 163 | const std::shared_ptr<Registry>& reg) | ||
747 | 164 | { | ||
748 | 165 | return reg->impl->appStopped(reg); | ||
749 | 166 | } | ||
750 | 167 | |||
751 | 168 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, Registry::FailureType>& | ||
752 | 169 | Registry::appFailed(const std::shared_ptr<Registry>& reg) | ||
753 | 170 | { | ||
754 | 171 | return reg->impl->appFailed(reg); | ||
755 | 172 | } | ||
756 | 173 | |||
757 | 174 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&>& | ||
758 | 175 | Registry::appPaused(const std::shared_ptr<Registry>& reg) | ||
759 | 176 | { | ||
760 | 177 | return reg->impl->appPaused(reg); | ||
761 | 178 | } | ||
762 | 179 | |||
763 | 180 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&>& | ||
764 | 181 | Registry::appResumed(const std::shared_ptr<Registry>& reg) | ||
765 | 182 | { | ||
766 | 183 | return reg->impl->appResumed(reg); | ||
767 | 184 | } | ||
768 | 185 | |||
769 | 146 | } // namespace app_launch | 186 | } // namespace app_launch |
770 | 147 | } // namespace ubuntu | 187 | } // namespace ubuntu |
771 | 148 | 188 | ||
772 | === modified file 'libubuntu-app-launch/registry.h' | |||
773 | --- libubuntu-app-launch/registry.h 2016-06-09 14:55:34 +0000 | |||
774 | +++ libubuntu-app-launch/registry.h 2016-11-07 20:56:13 +0000 | |||
775 | @@ -73,28 +73,134 @@ | |||
776 | 73 | */ | 73 | */ |
777 | 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()); |
778 | 75 | 75 | ||
779 | 76 | #if 0 /* TODO -- In next MR */ | ||
780 | 77 | /* Signals to discover what is happening to apps */ | 76 | /* Signals to discover what is happening to apps */ |
789 | 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 |
790 | 79 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> appStopped; | 78 | started. |
791 | 80 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, FailureType> appFailed; | 79 | |
792 | 81 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> appPaused; | 80 | \note This singal handler is activated on the UAL thread, if you want |
793 | 82 | core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> appResumed; | 81 | to execute on a different thread you'll need to move the work. |
794 | 83 | 82 | ||
795 | 84 | /* The Application Manager, almost always if you're not Unity8, don't | 83 | \param reg Registry to get the handler from |
796 | 85 | use this API. Testing is a special case. */ | 84 | */ |
797 | 85 | static core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>>& appStarted( | ||
798 | 86 | const std::shared_ptr<Registry>& reg = getDefault()); | ||
799 | 87 | |||
800 | 88 | /** Get the signal object that is signaled when an application has stopped. | ||
801 | 89 | |||
802 | 90 | \note This singal handler is activated on the UAL thread, if you want | ||
803 | 91 | to execute on a different thread you'll need to move the work. | ||
804 | 92 | |||
805 | 93 | \param reg Registry to get the handler from | ||
806 | 94 | */ | ||
807 | 95 | static core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>>& appStopped( | ||
808 | 96 | const std::shared_ptr<Registry>& reg = getDefault()); | ||
809 | 97 | |||
810 | 98 | /** Get the signal object that is signaled when an application has failed. | ||
811 | 99 | |||
812 | 100 | \note This singal handler is activated on the UAL thread, if you want | ||
813 | 101 | to execute on a different thread you'll need to move the work. | ||
814 | 102 | |||
815 | 103 | \param reg Registry to get the handler from | ||
816 | 104 | */ | ||
817 | 105 | static core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, FailureType>& appFailed( | ||
818 | 106 | const std::shared_ptr<Registry>& reg = getDefault()); | ||
819 | 107 | |||
820 | 108 | /** Get the signal object that is signaled when an application has been | ||
821 | 109 | paused. | ||
822 | 110 | |||
823 | 111 | \note This singal handler is activated on the UAL thread, if you want | ||
824 | 112 | to execute on a different thread you'll need to move the work. | ||
825 | 113 | |||
826 | 114 | \param reg Registry to get the handler from | ||
827 | 115 | */ | ||
828 | 116 | static core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&>& | ||
829 | 117 | appPaused(const std::shared_ptr<Registry>& reg = getDefault()); | ||
830 | 118 | |||
831 | 119 | /** Get the signal object that is signaled when an application has been | ||
832 | 120 | resumed. | ||
833 | 121 | |||
834 | 122 | \note This singal handler is activated on the UAL thread, if you want | ||
835 | 123 | to execute on a different thread you'll need to move the work. | ||
836 | 124 | |||
837 | 125 | \param reg Registry to get the handler from | ||
838 | 126 | */ | ||
839 | 127 | static core::Signal<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>, std::vector<pid_t>&>& | ||
840 | 128 | appResumed(const std::shared_ptr<Registry>& reg = getDefault()); | ||
841 | 129 | |||
842 | 130 | /** The Application Manager, almost always if you're not Unity8, don't | ||
843 | 131 | use this API. Testing is a special case. Subclass this interface and | ||
844 | 132 | implement these functions. | ||
845 | 133 | |||
846 | 134 | Each function here is being passed a function object that takes a boolean | ||
847 | 135 | to reply. This will accept or reject the request. The function object | ||
848 | 136 | can be copied to another thread and executed if needed. | ||
849 | 137 | */ | ||
850 | 86 | class Manager | 138 | class Manager |
851 | 87 | { | 139 | { |
854 | 88 | virtual bool focusRequest (std::shared_ptr<Application> app, std::shared_ptr<Application::Instance> instance) = 0; | 140 | public: |
855 | 89 | virtual bool startingRequest (std::shared_ptr<Application> app, std::shared_ptr<Application::Instance> instance) = 0; | 141 | /** Application wishes to startup |
856 | 142 | |||
857 | 143 | \note This singal handler is activated on the UAL thread, if you want | ||
858 | 144 | to execute on a different thread you'll need to move the work. | ||
859 | 145 | |||
860 | 146 | \param app Application requesting startup | ||
861 | 147 | \param instance Instance of the app, always valid but not useful | ||
862 | 148 | unless mulit-instance app. | ||
863 | 149 | \param reply Function object to reply if it is allowed to start | ||
864 | 150 | */ | ||
865 | 151 | virtual void startingRequest(std::shared_ptr<Application> app, | ||
866 | 152 | std::shared_ptr<Application::Instance> instance, | ||
867 | 153 | std::function<void(bool)> reply) = 0; | ||
868 | 154 | |||
869 | 155 | /** Application wishes to have focus. Usually this occurs when | ||
870 | 156 | a URL for the application is activated and the running app is | ||
871 | 157 | requested. | ||
872 | 158 | |||
873 | 159 | \note This singal handler is activated on the UAL thread, if you want | ||
874 | 160 | to execute on a different thread you'll need to move the work. | ||
875 | 161 | |||
876 | 162 | \param app Application requesting focus | ||
877 | 163 | \param instance Instance of the app, always valid but not useful | ||
878 | 164 | unless mulit-instance app. | ||
879 | 165 | \param reply Function object to reply if it is allowed to focus | ||
880 | 166 | */ | ||
881 | 167 | virtual void focusRequest(std::shared_ptr<Application> app, | ||
882 | 168 | std::shared_ptr<Application::Instance> instance, | ||
883 | 169 | std::function<void(bool)> reply) = 0; | ||
884 | 170 | |||
885 | 171 | /** Application wishes to resume. Usually this occurs when | ||
886 | 172 | a URL for the application is activated and the running app is | ||
887 | 173 | requested. | ||
888 | 174 | |||
889 | 175 | \note This singal handler is activated on the UAL thread, if you want | ||
890 | 176 | to execute on a different thread you'll need to move the work. | ||
891 | 177 | |||
892 | 178 | \param app Application requesting resume | ||
893 | 179 | \param instance Instance of the app, always valid but not useful | ||
894 | 180 | unless mulit-instance app. | ||
895 | 181 | \param reply Function object to reply if it is allowed to resume | ||
896 | 182 | */ | ||
897 | 183 | virtual void resumeRequest(std::shared_ptr<Application> app, | ||
898 | 184 | std::shared_ptr<Application::Instance> instance, | ||
899 | 185 | std::function<void(bool)> reply) = 0; | ||
900 | 90 | 186 | ||
901 | 91 | protected: | 187 | protected: |
902 | 92 | Manager() = default; | 188 | Manager() = default; |
903 | 93 | }; | 189 | }; |
904 | 94 | 190 | ||
908 | 95 | void setManager (Manager* manager); | 191 | /** Set the manager of applications, which gives permissions for them to |
909 | 96 | void clearManager (); | 192 | start and gain focus. In almost all cases this should be Unity8 as it |
910 | 97 | #endif | 193 | will be controlling applications. |
911 | 194 | |||
912 | 195 | This function will failure if there is already a manager set. | ||
913 | 196 | |||
914 | 197 | \param manager A reference to the Manager object to call | ||
915 | 198 | \param registry Registry to register the manager on | ||
916 | 199 | */ | ||
917 | 200 | static void setManager(std::shared_ptr<Manager> manager, std::shared_ptr<Registry> registry); | ||
918 | 201 | |||
919 | 202 | /** Remove the current manager on the registry */ | ||
920 | 203 | void clearManager(); | ||
921 | 98 | 204 | ||
922 | 99 | /* Helper Lists */ | 205 | /* Helper Lists */ |
923 | 100 | /** Get a list of all the helpers for a given helper type | 206 | /** Get a list of all the helpers for a given helper type |
924 | 101 | 207 | ||
925 | === modified file 'libubuntu-app-launch/ubuntu-app-launch.cpp' | |||
926 | --- libubuntu-app-launch/ubuntu-app-launch.cpp 2016-09-14 21:58:39 +0000 | |||
927 | +++ libubuntu-app-launch/ubuntu-app-launch.cpp 2016-11-07 20:56:13 +0000 | |||
928 | @@ -39,6 +39,7 @@ | |||
929 | 39 | #include "appid.h" | 39 | #include "appid.h" |
930 | 40 | #include "registry.h" | 40 | #include "registry.h" |
931 | 41 | #include "registry-impl.h" | 41 | #include "registry-impl.h" |
932 | 42 | #include <algorithm> | ||
933 | 42 | 43 | ||
934 | 43 | static void free_helper (gpointer value); | 44 | static void free_helper (gpointer value); |
935 | 44 | int kill (pid_t pid, int signal) noexcept; | 45 | int kill (pid_t pid, int signal) noexcept; |
936 | @@ -271,155 +272,210 @@ | |||
937 | 271 | gpointer user_data; | 272 | gpointer user_data; |
938 | 272 | }; | 273 | }; |
939 | 273 | 274 | ||
1043 | 274 | /* The data we keep for each failed observer */ | 275 | /* Function to take a work function and have it execute on a given |
1044 | 275 | typedef struct _paused_resumed_observer_t paused_resumed_observer_t; | 276 | GMainContext */ |
1045 | 276 | struct _paused_resumed_observer_t { | 277 | static void executeOnContext (std::shared_ptr<GMainContext> context, std::function<void()> work) |
1046 | 277 | GDBusConnection * conn; | 278 | { |
1047 | 278 | guint sighandle; | 279 | if (!context) { |
1048 | 279 | UbuntuAppLaunchAppPausedResumedObserver func; | 280 | work(); |
1049 | 280 | gpointer user_data; | 281 | return; |
1050 | 281 | const gchar * lttng_signal; | 282 | } |
1051 | 282 | }; | 283 | |
1052 | 283 | 284 | auto heapWork = new std::function<void()>(work); | |
1053 | 284 | /* The lists of Observers */ | 285 | |
1054 | 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); }); |
1055 | 286 | static GList * started_array = NULL; | 287 | g_source_set_callback(source.get(), |
1056 | 287 | static GList * stop_array = NULL; | 288 | [](gpointer data) { |
1057 | 288 | static GList * focus_array = NULL; | 289 | auto heapWork = static_cast<std::function<void()>*>(data); |
1058 | 289 | static GList * resume_array = NULL; | 290 | (*heapWork)(); |
1059 | 290 | static GList * failed_array = NULL; | 291 | return G_SOURCE_REMOVE; |
1060 | 291 | static GList * paused_array = NULL; | 292 | }, |
1061 | 292 | static GList * resumed_array = NULL; | 293 | heapWork, |
1062 | 293 | 294 | [](gpointer data) { | |
1063 | 294 | static void | 295 | auto heapWork = static_cast<std::function<void()>*>(data); |
1064 | 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; |
1065 | 296 | { | 297 | }); |
1066 | 297 | observer_t * observer = (observer_t *)user_data; | 298 | |
1067 | 298 | 299 | g_source_attach(source.get(), context.get()); | |
1068 | 299 | const gchar * signalname = NULL; | 300 | } |
1069 | 300 | g_variant_get_child(params, 0, "&s", &signalname); | 301 | |
1070 | 301 | 302 | /* Map of all the observers listening for app started */ | |
1071 | 302 | ual_tracepoint(observer_start, signalname); | 303 | static std::map<std::pair<UbuntuAppLaunchAppObserver, gpointer>, core::ScopedConnection> appStartedObservers; |
969 | 303 | |||
970 | 304 | gchar * env = NULL; | ||
971 | 305 | GVariant * envs = g_variant_get_child_value(params, 1); | ||
972 | 306 | GVariantIter iter; | ||
973 | 307 | g_variant_iter_init(&iter, envs); | ||
974 | 308 | |||
975 | 309 | gboolean job_found = FALSE; | ||
976 | 310 | gboolean job_legacy = FALSE; | ||
977 | 311 | gchar * instance = NULL; | ||
978 | 312 | |||
979 | 313 | while (g_variant_iter_loop(&iter, "s", &env)) { | ||
980 | 314 | if (g_strcmp0(env, "JOB=application-click") == 0) { | ||
981 | 315 | job_found = TRUE; | ||
982 | 316 | } else if (g_strcmp0(env, "JOB=application-legacy") == 0) { | ||
983 | 317 | job_found = TRUE; | ||
984 | 318 | job_legacy = TRUE; | ||
985 | 319 | } else if (g_strcmp0(env, "JOB=application-snap") == 0) { | ||
986 | 320 | job_found = TRUE; | ||
987 | 321 | job_legacy = TRUE; | ||
988 | 322 | } else if (g_str_has_prefix(env, "INSTANCE=")) { | ||
989 | 323 | instance = g_strdup(env + strlen("INSTANCE=")); | ||
990 | 324 | } | ||
991 | 325 | } | ||
992 | 326 | |||
993 | 327 | g_variant_unref(envs); | ||
994 | 328 | |||
995 | 329 | if (job_legacy && instance != NULL) { | ||
996 | 330 | gchar * dash = g_strrstr(instance, "-"); | ||
997 | 331 | if (dash != NULL) { | ||
998 | 332 | dash[0] = '\0'; | ||
999 | 333 | } | ||
1000 | 334 | } | ||
1001 | 335 | |||
1002 | 336 | if (job_found && instance != NULL) { | ||
1003 | 337 | observer->func(instance, observer->user_data); | ||
1004 | 338 | } | ||
1005 | 339 | |||
1006 | 340 | ual_tracepoint(observer_finish, signalname); | ||
1007 | 341 | |||
1008 | 342 | g_free(instance); | ||
1009 | 343 | } | ||
1010 | 344 | |||
1011 | 345 | /* Creates the observer structure and registers for the signal with | ||
1012 | 346 | GDBus so that we can get a callback */ | ||
1013 | 347 | static gboolean | ||
1014 | 348 | add_app_generic (UbuntuAppLaunchAppObserver observer, gpointer user_data, const gchar * signal, GList ** list) | ||
1015 | 349 | { | ||
1016 | 350 | GDBusConnection * conn = gdbus_upstart_ref(); | ||
1017 | 351 | |||
1018 | 352 | if (conn == NULL) { | ||
1019 | 353 | return FALSE; | ||
1020 | 354 | } | ||
1021 | 355 | |||
1022 | 356 | observer_t * observert = g_new0(observer_t, 1); | ||
1023 | 357 | |||
1024 | 358 | observert->conn = conn; | ||
1025 | 359 | observert->func = observer; | ||
1026 | 360 | observert->user_data = user_data; | ||
1027 | 361 | |||
1028 | 362 | *list = g_list_prepend(*list, observert); | ||
1029 | 363 | |||
1030 | 364 | observert->sighandle = g_dbus_connection_signal_subscribe(conn, | ||
1031 | 365 | NULL, /* sender */ | ||
1032 | 366 | DBUS_INTERFACE_UPSTART, /* interface */ | ||
1033 | 367 | "EventEmitted", /* signal */ | ||
1034 | 368 | DBUS_PATH_UPSTART, /* path */ | ||
1035 | 369 | signal, /* arg0 */ | ||
1036 | 370 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
1037 | 371 | observer_cb, | ||
1038 | 372 | observert, | ||
1039 | 373 | NULL); /* user data destroy */ | ||
1040 | 374 | |||
1041 | 375 | return TRUE; | ||
1042 | 376 | } | ||
1072 | 377 | 304 | ||
1073 | 378 | gboolean | 305 | gboolean |
1074 | 379 | ubuntu_app_launch_observer_add_app_started (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 306 | ubuntu_app_launch_observer_add_app_started (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1075 | 380 | { | 307 | { |
1078 | 381 | return add_app_generic(observer, user_data, "started", &started_array); | 308 | auto context = std::shared_ptr<GMainContext>(g_main_context_ref_thread_default(), [](GMainContext * context) { g_clear_pointer(&context, g_main_context_unref); }); |
1079 | 382 | } | 309 | |
1080 | 310 | appStartedObservers.emplace(std::make_pair( | ||
1081 | 311 | std::make_pair(observer, user_data), | ||
1082 | 312 | core::ScopedConnection( | ||
1083 | 313 | ubuntu::app_launch::Registry::appStarted().connect([context, observer, user_data](std::shared_ptr<ubuntu::app_launch::Application> app, std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { | ||
1084 | 314 | std::string appid = app->appId(); | ||
1085 | 315 | executeOnContext(context, [appid, observer, user_data]() { | ||
1086 | 316 | observer(appid.c_str(), user_data); | ||
1087 | 317 | }); | ||
1088 | 318 | }) | ||
1089 | 319 | ) | ||
1090 | 320 | )); | ||
1091 | 321 | |||
1092 | 322 | return TRUE; | ||
1093 | 323 | } | ||
1094 | 324 | |||
1095 | 325 | gboolean | ||
1096 | 326 | ubuntu_app_launch_observer_delete_app_started (UbuntuAppLaunchAppObserver observer, gpointer user_data) | ||
1097 | 327 | { | ||
1098 | 328 | auto iter = appStartedObservers.find(std::make_pair(observer, user_data)); | ||
1099 | 329 | |||
1100 | 330 | if (iter == appStartedObservers.end()) { | ||
1101 | 331 | return FALSE; | ||
1102 | 332 | } | ||
1103 | 333 | |||
1104 | 334 | appStartedObservers.erase(iter); | ||
1105 | 335 | return TRUE; | ||
1106 | 336 | } | ||
1107 | 337 | |||
1108 | 338 | /* Map of all the observers listening for app stopped */ | ||
1109 | 339 | static std::map<std::pair<UbuntuAppLaunchAppObserver, gpointer>, core::ScopedConnection> appStoppedObservers; | ||
1110 | 383 | 340 | ||
1111 | 384 | gboolean | 341 | gboolean |
1112 | 385 | ubuntu_app_launch_observer_add_app_stop (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 342 | ubuntu_app_launch_observer_add_app_stop (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1113 | 386 | { | 343 | { |
1115 | 387 | return add_app_generic(observer, user_data, "stopped", &stop_array); | 344 | auto context = std::shared_ptr<GMainContext>(g_main_context_ref_thread_default(), [](GMainContext * context) { g_clear_pointer(&context, g_main_context_unref); }); |
1116 | 345 | |||
1117 | 346 | appStoppedObservers.emplace(std::make_pair( | ||
1118 | 347 | std::make_pair(observer, user_data), | ||
1119 | 348 | core::ScopedConnection( | ||
1120 | 349 | ubuntu::app_launch::Registry::appStopped().connect([context, observer, user_data](std::shared_ptr<ubuntu::app_launch::Application> app, std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { | ||
1121 | 350 | std::string appid = app->appId(); | ||
1122 | 351 | executeOnContext(context, [appid, observer, user_data]() { | ||
1123 | 352 | observer(appid.c_str(), user_data); | ||
1124 | 353 | }); | ||
1125 | 354 | }) | ||
1126 | 355 | ) | ||
1127 | 356 | )); | ||
1128 | 357 | |||
1129 | 358 | return TRUE; | ||
1130 | 388 | } | 359 | } |
1131 | 389 | 360 | ||
1136 | 390 | /* Creates the observer structure and registers for the signal with | 361 | gboolean |
1137 | 391 | GDBus so that we can get a callback */ | 362 | ubuntu_app_launch_observer_delete_app_stop (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1134 | 392 | static gboolean | ||
1135 | 393 | add_session_generic (UbuntuAppLaunchAppObserver observer, gpointer user_data, const gchar * signal, GList ** list, GDBusSignalCallback session_cb) | ||
1138 | 394 | { | 363 | { |
1140 | 395 | GDBusConnection * conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | 364 | auto iter = appStoppedObservers.find(std::make_pair(observer, user_data)); |
1141 | 396 | 365 | ||
1143 | 397 | if (conn == NULL) { | 366 | if (iter == appStoppedObservers.end()) { |
1144 | 398 | return FALSE; | 367 | return FALSE; |
1145 | 399 | } | 368 | } |
1146 | 400 | 369 | ||
1166 | 401 | observer_t * observert = g_new0(observer_t, 1); | 370 | appStoppedObservers.erase(iter); |
1148 | 402 | |||
1149 | 403 | observert->conn = conn; | ||
1150 | 404 | observert->func = observer; | ||
1151 | 405 | observert->user_data = user_data; | ||
1152 | 406 | |||
1153 | 407 | *list = g_list_prepend(*list, observert); | ||
1154 | 408 | |||
1155 | 409 | observert->sighandle = g_dbus_connection_signal_subscribe(conn, | ||
1156 | 410 | NULL, /* sender */ | ||
1157 | 411 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
1158 | 412 | signal, /* signal */ | ||
1159 | 413 | "/", /* path */ | ||
1160 | 414 | NULL, /* arg0 */ | ||
1161 | 415 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
1162 | 416 | session_cb, | ||
1163 | 417 | observert, | ||
1164 | 418 | NULL); /* user data destroy */ | ||
1165 | 419 | |||
1167 | 420 | return TRUE; | 371 | return TRUE; |
1168 | 421 | } | 372 | } |
1169 | 422 | 373 | ||
1170 | 374 | class CManager : public ubuntu::app_launch::Registry::Manager | ||
1171 | 375 | { | ||
1172 | 376 | public: | ||
1173 | 377 | CManager () { | ||
1174 | 378 | g_debug("Creating the CManager object"); | ||
1175 | 379 | } | ||
1176 | 380 | |||
1177 | 381 | void startingRequest(std::shared_ptr<ubuntu::app_launch::Application> app, | ||
1178 | 382 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, | ||
1179 | 383 | std::function<void(bool)> reply) override { | ||
1180 | 384 | std::string sappid = app->appId(); | ||
1181 | 385 | g_debug("CManager starting: %s", sappid.c_str()); | ||
1182 | 386 | |||
1183 | 387 | for (const auto &data : startingList) { | ||
1184 | 388 | executeOnContext(data.context, [data, sappid]() { | ||
1185 | 389 | data.observer(sappid.c_str(), data.user_data); | ||
1186 | 390 | }); | ||
1187 | 391 | } | ||
1188 | 392 | |||
1189 | 393 | reply(true); | ||
1190 | 394 | } | ||
1191 | 395 | |||
1192 | 396 | void focusRequest(std::shared_ptr<ubuntu::app_launch::Application> app, | ||
1193 | 397 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, | ||
1194 | 398 | std::function<void(bool)> reply) override { | ||
1195 | 399 | std::string sappid = app->appId(); | ||
1196 | 400 | g_debug("CManager focus: %s", sappid.c_str()); | ||
1197 | 401 | |||
1198 | 402 | for (const auto &data : focusList) { | ||
1199 | 403 | executeOnContext(data.context, [data, sappid]() { | ||
1200 | 404 | data.observer(sappid.c_str(), data.user_data); | ||
1201 | 405 | }); | ||
1202 | 406 | } | ||
1203 | 407 | |||
1204 | 408 | reply(true); | ||
1205 | 409 | } | ||
1206 | 410 | |||
1207 | 411 | void resumeRequest(std::shared_ptr<ubuntu::app_launch::Application> app, | ||
1208 | 412 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, | ||
1209 | 413 | std::function<void(bool)> reply) override { | ||
1210 | 414 | std::string sappid = app->appId(); | ||
1211 | 415 | g_debug("CManager resume: %s", sappid.c_str()); | ||
1212 | 416 | |||
1213 | 417 | for (const auto &data : resumeList) { | ||
1214 | 418 | executeOnContext(data.context, [data, sappid]() { | ||
1215 | 419 | data.observer(sappid.c_str(), data.user_data); | ||
1216 | 420 | }); | ||
1217 | 421 | } | ||
1218 | 422 | |||
1219 | 423 | reply(true); | ||
1220 | 424 | } | ||
1221 | 425 | |||
1222 | 426 | private: | ||
1223 | 427 | struct ObserverData { | ||
1224 | 428 | UbuntuAppLaunchAppObserver observer; | ||
1225 | 429 | gpointer user_data; | ||
1226 | 430 | std::shared_ptr<GMainContext> context; | ||
1227 | 431 | |||
1228 | 432 | ObserverData(UbuntuAppLaunchAppObserver obs, gpointer ud) | ||
1229 | 433 | : observer(obs) | ||
1230 | 434 | , user_data(ud) { | ||
1231 | 435 | context = std::shared_ptr<GMainContext>(g_main_context_ref_thread_default(), [](GMainContext * context) { g_clear_pointer(&context, g_main_context_unref); }); | ||
1232 | 436 | } | ||
1233 | 437 | }; | ||
1234 | 438 | |||
1235 | 439 | std::list<ObserverData> focusList; | ||
1236 | 440 | std::list<ObserverData> resumeList; | ||
1237 | 441 | std::list<ObserverData> startingList; | ||
1238 | 442 | |||
1239 | 443 | bool removeList (std::list<ObserverData> &list, UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1240 | 444 | auto iter = std::find_if(list.begin(), list.end(), [observer, user_data](const ObserverData &data) { | ||
1241 | 445 | return data.observer == observer && data.user_data == user_data; | ||
1242 | 446 | }); | ||
1243 | 447 | |||
1244 | 448 | if (iter == list.end()) { | ||
1245 | 449 | return false; | ||
1246 | 450 | } | ||
1247 | 451 | |||
1248 | 452 | list.erase(iter); | ||
1249 | 453 | return true; | ||
1250 | 454 | } | ||
1251 | 455 | |||
1252 | 456 | public: | ||
1253 | 457 | void addFocus (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1254 | 458 | focusList.emplace_back(ObserverData(observer, user_data)); | ||
1255 | 459 | } | ||
1256 | 460 | void addResume (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1257 | 461 | resumeList.emplace_back(ObserverData(observer, user_data)); | ||
1258 | 462 | } | ||
1259 | 463 | void addStarting (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1260 | 464 | startingList.emplace_back(ObserverData(observer, user_data)); | ||
1261 | 465 | } | ||
1262 | 466 | bool deleteFocus (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1263 | 467 | return removeList(focusList, observer, user_data); | ||
1264 | 468 | } | ||
1265 | 469 | bool deleteResume (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1266 | 470 | return removeList(resumeList, observer, user_data); | ||
1267 | 471 | } | ||
1268 | 472 | bool deleteStarting (UbuntuAppLaunchAppObserver observer, gpointer user_data) { | ||
1269 | 473 | return removeList(startingList, observer, user_data); | ||
1270 | 474 | } | ||
1271 | 475 | }; | ||
1272 | 476 | |||
1273 | 477 | static std::weak_ptr<CManager> cmanager; | ||
1274 | 478 | |||
1275 | 423 | /* Generic handler for a bunch of our signals */ | 479 | /* Generic handler for a bunch of our signals */ |
1276 | 424 | static inline void | 480 | static inline void |
1277 | 425 | generic_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | 481 | generic_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) |
1278 | @@ -433,328 +489,158 @@ | |||
1279 | 433 | } | 489 | } |
1280 | 434 | } | 490 | } |
1281 | 435 | 491 | ||
1282 | 436 | /* Handle the focus signal when it occurs, call the observer */ | ||
1283 | 437 | static void | ||
1284 | 438 | focus_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | ||
1285 | 439 | { | ||
1286 | 440 | ual_tracepoint(observer_start, "focus"); | ||
1287 | 441 | |||
1288 | 442 | generic_signal_cb(conn, sender, object, interface, signal, params, user_data); | ||
1289 | 443 | |||
1290 | 444 | ual_tracepoint(observer_finish, "focus"); | ||
1291 | 445 | } | ||
1292 | 446 | |||
1293 | 447 | gboolean | 492 | gboolean |
1294 | 448 | ubuntu_app_launch_observer_add_app_focus (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 493 | ubuntu_app_launch_observer_add_app_focus (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1295 | 449 | { | 494 | { |
1297 | 450 | return add_session_generic(observer, user_data, "UnityFocusRequest", &focus_array, focus_signal_cb); | 495 | auto manager = cmanager.lock(); |
1298 | 496 | |||
1299 | 497 | if (!manager) { | ||
1300 | 498 | manager = std::make_shared<CManager>(); | ||
1301 | 499 | ubuntu::app_launch::Registry::setManager(manager, ubuntu::app_launch::Registry::getDefault()); | ||
1302 | 500 | cmanager = manager; | ||
1303 | 501 | } | ||
1304 | 502 | |||
1305 | 503 | manager->addFocus(observer, user_data); | ||
1306 | 504 | return TRUE; | ||
1307 | 451 | } | 505 | } |
1308 | 452 | 506 | ||
1312 | 453 | /* Handle the resume signal when it occurs, call the observer, then send a signal back when we're done */ | 507 | gboolean |
1313 | 454 | static void | 508 | ubuntu_app_launch_observer_delete_app_focus (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1311 | 455 | resume_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | ||
1314 | 456 | { | 509 | { |
1331 | 457 | ual_tracepoint(observer_start, "resume"); | 510 | auto manager = cmanager.lock(); |
1332 | 458 | 511 | ||
1333 | 459 | generic_signal_cb(conn, sender, object, interface, signal, params, user_data); | 512 | if (!manager) { |
1334 | 460 | 513 | return FALSE; | |
1319 | 461 | GError * error = NULL; | ||
1320 | 462 | g_dbus_connection_emit_signal(conn, | ||
1321 | 463 | sender, /* destination */ | ||
1322 | 464 | "/", /* path */ | ||
1323 | 465 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
1324 | 466 | "UnityResumeResponse", /* signal */ | ||
1325 | 467 | params, /* params, the same */ | ||
1326 | 468 | &error); | ||
1327 | 469 | |||
1328 | 470 | if (error != NULL) { | ||
1329 | 471 | g_warning("Unable to emit response signal: %s", error->message); | ||
1330 | 472 | g_error_free(error); | ||
1335 | 473 | } | 514 | } |
1336 | 474 | 515 | ||
1338 | 475 | ual_tracepoint(observer_finish, "resume"); | 516 | return manager->deleteFocus(observer, user_data) ? TRUE : FALSE; |
1339 | 476 | } | 517 | } |
1340 | 477 | 518 | ||
1341 | 478 | gboolean | 519 | gboolean |
1342 | 479 | ubuntu_app_launch_observer_add_app_resume (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 520 | ubuntu_app_launch_observer_add_app_resume (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1343 | 480 | { | 521 | { |
1345 | 481 | return add_session_generic(observer, user_data, "UnityResumeRequest", &resume_array, resume_signal_cb); | 522 | auto manager = cmanager.lock(); |
1346 | 523 | |||
1347 | 524 | if (!manager) { | ||
1348 | 525 | manager = std::make_shared<CManager>(); | ||
1349 | 526 | ubuntu::app_launch::Registry::setManager(manager, ubuntu::app_launch::Registry::getDefault()); | ||
1350 | 527 | cmanager = manager; | ||
1351 | 528 | } | ||
1352 | 529 | |||
1353 | 530 | manager->addResume(observer, user_data); | ||
1354 | 531 | return TRUE; | ||
1355 | 482 | } | 532 | } |
1356 | 483 | 533 | ||
1360 | 484 | /* Handle the starting signal when it occurs, call the observer, then send a signal back when we're done */ | 534 | gboolean |
1361 | 485 | static void | 535 | ubuntu_app_launch_observer_delete_app_resume (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1359 | 486 | starting_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | ||
1362 | 487 | { | 536 | { |
1379 | 488 | ual_tracepoint(observer_start, "starting"); | 537 | auto manager = cmanager.lock(); |
1380 | 489 | 538 | ||
1381 | 490 | generic_signal_cb(conn, sender, object, interface, signal, params, user_data); | 539 | if (!manager) { |
1382 | 491 | 540 | return FALSE; | |
1367 | 492 | GError * error = NULL; | ||
1368 | 493 | g_dbus_connection_emit_signal(conn, | ||
1369 | 494 | sender, /* destination */ | ||
1370 | 495 | "/", /* path */ | ||
1371 | 496 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
1372 | 497 | "UnityStartingSignal", /* signal */ | ||
1373 | 498 | params, /* params, the same */ | ||
1374 | 499 | &error); | ||
1375 | 500 | |||
1376 | 501 | if (error != NULL) { | ||
1377 | 502 | g_warning("Unable to emit response signal: %s", error->message); | ||
1378 | 503 | g_error_free(error); | ||
1383 | 504 | } | 541 | } |
1384 | 505 | 542 | ||
1386 | 506 | ual_tracepoint(observer_finish, "starting"); | 543 | return manager->deleteResume(observer, user_data) ? TRUE : FALSE; |
1387 | 507 | } | 544 | } |
1388 | 508 | 545 | ||
1389 | 509 | gboolean | 546 | gboolean |
1390 | 510 | ubuntu_app_launch_observer_add_app_starting (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 547 | ubuntu_app_launch_observer_add_app_starting (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1391 | 511 | { | 548 | { |
1392 | 549 | auto manager = cmanager.lock(); | ||
1393 | 550 | |||
1394 | 551 | if (!manager) { | ||
1395 | 552 | manager = std::make_shared<CManager>(); | ||
1396 | 553 | ubuntu::app_launch::Registry::setManager(manager, ubuntu::app_launch::Registry::getDefault()); | ||
1397 | 554 | cmanager = manager; | ||
1398 | 555 | } | ||
1399 | 556 | |||
1400 | 512 | ubuntu::app_launch::Registry::Impl::watchingAppStarting(true); | 557 | ubuntu::app_launch::Registry::Impl::watchingAppStarting(true); |
1587 | 513 | return add_session_generic(observer, user_data, "UnityStartingBroadcast", &starting_array, starting_signal_cb); | 558 | manager->addStarting(observer, user_data); |
1588 | 514 | } | 559 | return TRUE; |
1403 | 515 | |||
1404 | 516 | /* Handle the failed signal when it occurs, call the observer */ | ||
1405 | 517 | static void | ||
1406 | 518 | failed_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | ||
1407 | 519 | { | ||
1408 | 520 | failed_observer_t * observer = (failed_observer_t *)user_data; | ||
1409 | 521 | const gchar * appid = NULL; | ||
1410 | 522 | const gchar * typestr = NULL; | ||
1411 | 523 | |||
1412 | 524 | ual_tracepoint(observer_start, "failed"); | ||
1413 | 525 | |||
1414 | 526 | if (observer->func != NULL) { | ||
1415 | 527 | UbuntuAppLaunchAppFailed type = UBUNTU_APP_LAUNCH_APP_FAILED_CRASH; | ||
1416 | 528 | g_variant_get(params, "(&s&s)", &appid, &typestr); | ||
1417 | 529 | |||
1418 | 530 | if (g_strcmp0("crash", typestr) == 0) { | ||
1419 | 531 | type = UBUNTU_APP_LAUNCH_APP_FAILED_CRASH; | ||
1420 | 532 | } else if (g_strcmp0("start-failure", typestr) == 0) { | ||
1421 | 533 | type = UBUNTU_APP_LAUNCH_APP_FAILED_START_FAILURE; | ||
1422 | 534 | } else { | ||
1423 | 535 | g_warning("Application failure type '%s' unknown, reporting as a crash", typestr); | ||
1424 | 536 | } | ||
1425 | 537 | |||
1426 | 538 | observer->func(appid, type, observer->user_data); | ||
1427 | 539 | } | ||
1428 | 540 | |||
1429 | 541 | ual_tracepoint(observer_finish, "failed"); | ||
1430 | 542 | } | ||
1431 | 543 | |||
1432 | 544 | gboolean | ||
1433 | 545 | ubuntu_app_launch_observer_add_app_failed (UbuntuAppLaunchAppFailedObserver observer, gpointer user_data) | ||
1434 | 546 | { | ||
1435 | 547 | GDBusConnection * conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | ||
1436 | 548 | |||
1437 | 549 | if (conn == NULL) { | ||
1438 | 550 | return FALSE; | ||
1439 | 551 | } | ||
1440 | 552 | |||
1441 | 553 | failed_observer_t * observert = g_new0(failed_observer_t, 1); | ||
1442 | 554 | |||
1443 | 555 | observert->conn = conn; | ||
1444 | 556 | observert->func = observer; | ||
1445 | 557 | observert->user_data = user_data; | ||
1446 | 558 | |||
1447 | 559 | failed_array = g_list_prepend(failed_array, observert); | ||
1448 | 560 | |||
1449 | 561 | observert->sighandle = g_dbus_connection_signal_subscribe(conn, | ||
1450 | 562 | NULL, /* sender */ | ||
1451 | 563 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
1452 | 564 | "ApplicationFailed", /* signal */ | ||
1453 | 565 | "/", /* path */ | ||
1454 | 566 | NULL, /* arg0 */ | ||
1455 | 567 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
1456 | 568 | failed_signal_cb, | ||
1457 | 569 | observert, | ||
1458 | 570 | NULL); /* user data destroy */ | ||
1459 | 571 | |||
1460 | 572 | return TRUE; | ||
1461 | 573 | } | ||
1462 | 574 | |||
1463 | 575 | /* Handle the paused signal when it occurs, call the observer */ | ||
1464 | 576 | static void | ||
1465 | 577 | paused_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) | ||
1466 | 578 | { | ||
1467 | 579 | paused_resumed_observer_t * observer = (paused_resumed_observer_t *)user_data; | ||
1468 | 580 | |||
1469 | 581 | ual_tracepoint(observer_start, observer->lttng_signal); | ||
1470 | 582 | |||
1471 | 583 | if (observer->func != NULL) { | ||
1472 | 584 | GArray * pidarray = g_array_new(TRUE, TRUE, sizeof(GPid)); | ||
1473 | 585 | GVariant * appid = g_variant_get_child_value(params, 0); | ||
1474 | 586 | GVariant * pids = g_variant_get_child_value(params, 1); | ||
1475 | 587 | guint64 pid; | ||
1476 | 588 | GVariantIter thispid; | ||
1477 | 589 | g_variant_iter_init(&thispid, pids); | ||
1478 | 590 | |||
1479 | 591 | while (g_variant_iter_loop(&thispid, "t", &pid)) { | ||
1480 | 592 | GPid gpid = (GPid)pid; /* Should be a no-op for most architectures, but just in case */ | ||
1481 | 593 | g_array_append_val(pidarray, gpid); | ||
1482 | 594 | } | ||
1483 | 595 | |||
1484 | 596 | observer->func(g_variant_get_string(appid, NULL), (GPid *)pidarray->data, observer->user_data); | ||
1485 | 597 | |||
1486 | 598 | g_array_free(pidarray, TRUE); | ||
1487 | 599 | g_variant_unref(appid); | ||
1488 | 600 | g_variant_unref(pids); | ||
1489 | 601 | } | ||
1490 | 602 | |||
1491 | 603 | ual_tracepoint(observer_finish, observer->lttng_signal); | ||
1492 | 604 | } | ||
1493 | 605 | |||
1494 | 606 | static gboolean | ||
1495 | 607 | paused_resumed_generic (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data, GList ** queue, const gchar * signal_name, const gchar * lttng_signal) | ||
1496 | 608 | { | ||
1497 | 609 | GDBusConnection * conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | ||
1498 | 610 | |||
1499 | 611 | if (conn == NULL) { | ||
1500 | 612 | return FALSE; | ||
1501 | 613 | } | ||
1502 | 614 | |||
1503 | 615 | paused_resumed_observer_t * observert = g_new0(paused_resumed_observer_t, 1); | ||
1504 | 616 | |||
1505 | 617 | observert->conn = conn; | ||
1506 | 618 | observert->func = observer; | ||
1507 | 619 | observert->user_data = user_data; | ||
1508 | 620 | observert->lttng_signal = lttng_signal; | ||
1509 | 621 | |||
1510 | 622 | *queue = g_list_prepend(*queue, observert); | ||
1511 | 623 | |||
1512 | 624 | observert->sighandle = g_dbus_connection_signal_subscribe(conn, | ||
1513 | 625 | NULL, /* sender */ | ||
1514 | 626 | "com.canonical.UbuntuAppLaunch", /* interface */ | ||
1515 | 627 | signal_name, /* signal */ | ||
1516 | 628 | "/", /* path */ | ||
1517 | 629 | NULL, /* arg0 */ | ||
1518 | 630 | G_DBUS_SIGNAL_FLAGS_NONE, | ||
1519 | 631 | paused_signal_cb, | ||
1520 | 632 | observert, | ||
1521 | 633 | NULL); /* user data destroy */ | ||
1522 | 634 | |||
1523 | 635 | return TRUE; | ||
1524 | 636 | } | ||
1525 | 637 | |||
1526 | 638 | gboolean | ||
1527 | 639 | ubuntu_app_launch_observer_add_app_paused (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | ||
1528 | 640 | { | ||
1529 | 641 | return paused_resumed_generic(observer, user_data, &paused_array, "ApplicationPaused", "paused"); | ||
1530 | 642 | } | ||
1531 | 643 | |||
1532 | 644 | gboolean | ||
1533 | 645 | ubuntu_app_launch_observer_add_app_resumed (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | ||
1534 | 646 | { | ||
1535 | 647 | return paused_resumed_generic(observer, user_data, &resumed_array, "ApplicationResumed", "resumed"); | ||
1536 | 648 | } | ||
1537 | 649 | |||
1538 | 650 | static gboolean | ||
1539 | 651 | delete_app_generic (UbuntuAppLaunchAppObserver observer, gpointer user_data, GList ** list) | ||
1540 | 652 | { | ||
1541 | 653 | observer_t * observert = NULL; | ||
1542 | 654 | GList * look; | ||
1543 | 655 | |||
1544 | 656 | for (look = *list; look != NULL; look = g_list_next(look)) { | ||
1545 | 657 | observert = (observer_t *)look->data; | ||
1546 | 658 | |||
1547 | 659 | if (observert->func == observer && observert->user_data == user_data) { | ||
1548 | 660 | break; | ||
1549 | 661 | } | ||
1550 | 662 | } | ||
1551 | 663 | |||
1552 | 664 | if (look == NULL) { | ||
1553 | 665 | return FALSE; | ||
1554 | 666 | } | ||
1555 | 667 | |||
1556 | 668 | g_dbus_connection_signal_unsubscribe(observert->conn, observert->sighandle); | ||
1557 | 669 | g_object_unref(observert->conn); | ||
1558 | 670 | |||
1559 | 671 | g_free(observert); | ||
1560 | 672 | *list = g_list_delete_link(*list, look); | ||
1561 | 673 | |||
1562 | 674 | return TRUE; | ||
1563 | 675 | } | ||
1564 | 676 | |||
1565 | 677 | gboolean | ||
1566 | 678 | ubuntu_app_launch_observer_delete_app_started (UbuntuAppLaunchAppObserver observer, gpointer user_data) | ||
1567 | 679 | { | ||
1568 | 680 | return delete_app_generic(observer, user_data, &started_array); | ||
1569 | 681 | } | ||
1570 | 682 | |||
1571 | 683 | gboolean | ||
1572 | 684 | ubuntu_app_launch_observer_delete_app_stop (UbuntuAppLaunchAppObserver observer, gpointer user_data) | ||
1573 | 685 | { | ||
1574 | 686 | return delete_app_generic(observer, user_data, &stop_array); | ||
1575 | 687 | } | ||
1576 | 688 | |||
1577 | 689 | gboolean | ||
1578 | 690 | ubuntu_app_launch_observer_delete_app_resume (UbuntuAppLaunchAppObserver observer, gpointer user_data) | ||
1579 | 691 | { | ||
1580 | 692 | return delete_app_generic(observer, user_data, &resume_array); | ||
1581 | 693 | } | ||
1582 | 694 | |||
1583 | 695 | gboolean | ||
1584 | 696 | ubuntu_app_launch_observer_delete_app_focus (UbuntuAppLaunchAppObserver observer, gpointer user_data) | ||
1585 | 697 | { | ||
1586 | 698 | return delete_app_generic(observer, user_data, &focus_array); | ||
1589 | 699 | } | 560 | } |
1590 | 700 | 561 | ||
1591 | 701 | gboolean | 562 | gboolean |
1592 | 702 | ubuntu_app_launch_observer_delete_app_starting (UbuntuAppLaunchAppObserver observer, gpointer user_data) | 563 | ubuntu_app_launch_observer_delete_app_starting (UbuntuAppLaunchAppObserver observer, gpointer user_data) |
1593 | 703 | { | 564 | { |
1594 | 565 | auto manager = cmanager.lock(); | ||
1595 | 566 | |||
1596 | 567 | if (!manager) { | ||
1597 | 568 | return FALSE; | ||
1598 | 569 | } | ||
1599 | 570 | |||
1600 | 704 | ubuntu::app_launch::Registry::Impl::watchingAppStarting(false); | 571 | ubuntu::app_launch::Registry::Impl::watchingAppStarting(false); |
1602 | 705 | return delete_app_generic(observer, user_data, &starting_array); | 572 | return manager->deleteStarting(observer, user_data) ? TRUE : FALSE; |
1603 | 573 | } | ||
1604 | 574 | |||
1605 | 575 | /* Map of all the observers listening for app stopped */ | ||
1606 | 576 | static std::map<std::pair<UbuntuAppLaunchAppFailedObserver, gpointer>, core::ScopedConnection> appFailedObservers; | ||
1607 | 577 | |||
1608 | 578 | gboolean | ||
1609 | 579 | ubuntu_app_launch_observer_add_app_failed (UbuntuAppLaunchAppFailedObserver observer, gpointer user_data) | ||
1610 | 580 | { | ||
1611 | 581 | auto context = std::shared_ptr<GMainContext>(g_main_context_ref_thread_default(), [](GMainContext * context) { g_clear_pointer(&context, g_main_context_unref); }); | ||
1612 | 582 | |||
1613 | 583 | appFailedObservers.emplace(std::make_pair( | ||
1614 | 584 | std::make_pair(observer, user_data), | ||
1615 | 585 | core::ScopedConnection( | ||
1616 | 586 | 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) { | ||
1617 | 587 | std::string appid = app->appId(); | ||
1618 | 588 | executeOnContext(context, [appid, type, observer, user_data]() { | ||
1619 | 589 | UbuntuAppLaunchAppFailed ctype; | ||
1620 | 590 | |||
1621 | 591 | switch (type) { | ||
1622 | 592 | case ubuntu::app_launch::Registry::FailureType::CRASH: | ||
1623 | 593 | ctype = UBUNTU_APP_LAUNCH_APP_FAILED_CRASH; | ||
1624 | 594 | break; | ||
1625 | 595 | case ubuntu::app_launch::Registry::FailureType::START_FAILURE: | ||
1626 | 596 | ctype = UBUNTU_APP_LAUNCH_APP_FAILED_START_FAILURE; | ||
1627 | 597 | break; | ||
1628 | 598 | } | ||
1629 | 599 | |||
1630 | 600 | observer(appid.c_str(), ctype, user_data); | ||
1631 | 601 | }); | ||
1632 | 602 | }) | ||
1633 | 603 | ) | ||
1634 | 604 | )); | ||
1635 | 605 | |||
1636 | 606 | return TRUE; | ||
1637 | 706 | } | 607 | } |
1638 | 707 | 608 | ||
1639 | 708 | gboolean | 609 | gboolean |
1640 | 709 | ubuntu_app_launch_observer_delete_app_failed (UbuntuAppLaunchAppFailedObserver observer, gpointer user_data) | 610 | ubuntu_app_launch_observer_delete_app_failed (UbuntuAppLaunchAppFailedObserver observer, gpointer user_data) |
1641 | 710 | { | 611 | { |
1654 | 711 | failed_observer_t * observert = NULL; | 612 | auto iter = appFailedObservers.find(std::make_pair(observer, user_data)); |
1655 | 712 | GList * look; | 613 | |
1656 | 713 | 614 | if (iter == appFailedObservers.end()) { | |
1645 | 714 | for (look = failed_array; look != NULL; look = g_list_next(look)) { | ||
1646 | 715 | observert = (failed_observer_t *)look->data; | ||
1647 | 716 | |||
1648 | 717 | if (observert->func == observer && observert->user_data == user_data) { | ||
1649 | 718 | break; | ||
1650 | 719 | } | ||
1651 | 720 | } | ||
1652 | 721 | |||
1653 | 722 | if (look == NULL) { | ||
1657 | 723 | return FALSE; | 615 | return FALSE; |
1658 | 724 | } | 616 | } |
1659 | 725 | 617 | ||
1666 | 726 | g_dbus_connection_signal_unsubscribe(observert->conn, observert->sighandle); | 618 | appFailedObservers.erase(iter); |
1661 | 727 | g_object_unref(observert->conn); | ||
1662 | 728 | |||
1663 | 729 | g_free(observert); | ||
1664 | 730 | failed_array = g_list_delete_link(failed_array, look); | ||
1665 | 731 | |||
1667 | 732 | return TRUE; | 619 | return TRUE; |
1668 | 733 | } | 620 | } |
1669 | 734 | 621 | ||
1672 | 735 | static gboolean | 622 | static std::map<std::pair<UbuntuAppLaunchAppPausedResumedObserver, gpointer>, core::ScopedConnection> appPausedObservers; |
1673 | 736 | paused_resumed_delete (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data, GList ** list) | 623 | |
1674 | 624 | gboolean | ||
1675 | 625 | ubuntu_app_launch_observer_add_app_paused (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | ||
1676 | 737 | { | 626 | { |
1697 | 738 | paused_resumed_observer_t * observert = NULL; | 627 | auto context = std::shared_ptr<GMainContext>(g_main_context_ref_thread_default(), [](GMainContext * context) { g_clear_pointer(&context, g_main_context_unref); }); |
1698 | 739 | GList * look; | 628 | |
1699 | 740 | 629 | appPausedObservers.emplace(std::make_pair( | |
1700 | 741 | for (look = *list; look != NULL; look = g_list_next(look)) { | 630 | std::make_pair(observer, user_data), |
1701 | 742 | observert = (paused_resumed_observer_t *)look->data; | 631 | core::ScopedConnection( |
1702 | 743 | 632 | ubuntu::app_launch::Registry::appPaused().connect([context, observer, user_data](std::shared_ptr<ubuntu::app_launch::Application> app, std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, std::vector<pid_t> &pids) { | |
1703 | 744 | if (observert->func == observer && observert->user_data == user_data) { | 633 | std::vector<pid_t> lpids = pids; |
1704 | 745 | break; | 634 | lpids.emplace_back(0); |
1705 | 746 | } | 635 | |
1706 | 747 | } | 636 | std::string appid = app->appId(); |
1707 | 748 | 637 | ||
1708 | 749 | if (look == NULL) { | 638 | executeOnContext(context, [appid, observer, user_data, lpids]() { |
1709 | 750 | return FALSE; | 639 | observer(appid.c_str(), (int *)(lpids.data()), user_data); |
1710 | 751 | } | 640 | }); |
1711 | 752 | 641 | }) | |
1712 | 753 | g_dbus_connection_signal_unsubscribe(observert->conn, observert->sighandle); | 642 | ) |
1713 | 754 | g_object_unref(observert->conn); | 643 | )); |
1694 | 755 | |||
1695 | 756 | g_free(observert); | ||
1696 | 757 | *list = g_list_delete_link(*list, look); | ||
1714 | 758 | 644 | ||
1715 | 759 | return TRUE; | 645 | return TRUE; |
1716 | 760 | } | 646 | } |
1717 | @@ -762,13 +648,53 @@ | |||
1718 | 762 | gboolean | 648 | gboolean |
1719 | 763 | ubuntu_app_launch_observer_delete_app_paused (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | 649 | ubuntu_app_launch_observer_delete_app_paused (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) |
1720 | 764 | { | 650 | { |
1722 | 765 | return paused_resumed_delete(observer, user_data, &paused_array); | 651 | auto iter = appPausedObservers.find(std::make_pair(observer, user_data)); |
1723 | 652 | |||
1724 | 653 | if (iter == appPausedObservers.end()) { | ||
1725 | 654 | return FALSE; | ||
1726 | 655 | } | ||
1727 | 656 | |||
1728 | 657 | appPausedObservers.erase(iter); | ||
1729 | 658 | return TRUE; | ||
1730 | 659 | } | ||
1731 | 660 | |||
1732 | 661 | static std::map<std::pair<UbuntuAppLaunchAppPausedResumedObserver, gpointer>, core::ScopedConnection> appResumedObservers; | ||
1733 | 662 | |||
1734 | 663 | gboolean | ||
1735 | 664 | ubuntu_app_launch_observer_add_app_resumed (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | ||
1736 | 665 | { | ||
1737 | 666 | auto context = std::shared_ptr<GMainContext>(g_main_context_ref_thread_default(), [](GMainContext * context) { g_clear_pointer(&context, g_main_context_unref); }); | ||
1738 | 667 | |||
1739 | 668 | appResumedObservers.emplace(std::make_pair( | ||
1740 | 669 | std::make_pair(observer, user_data), | ||
1741 | 670 | core::ScopedConnection( | ||
1742 | 671 | ubuntu::app_launch::Registry::appResumed().connect([context, observer, user_data](std::shared_ptr<ubuntu::app_launch::Application> app, std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, std::vector<pid_t>& pids) { | ||
1743 | 672 | std::vector<pid_t> lpids = pids; | ||
1744 | 673 | lpids.emplace_back(0); | ||
1745 | 674 | |||
1746 | 675 | std::string appid = app->appId(); | ||
1747 | 676 | |||
1748 | 677 | executeOnContext(context, [appid, observer, user_data, lpids]() { | ||
1749 | 678 | observer(appid.c_str(), (int *)(lpids.data()), user_data); | ||
1750 | 679 | }); | ||
1751 | 680 | }) | ||
1752 | 681 | ) | ||
1753 | 682 | )); | ||
1754 | 683 | |||
1755 | 684 | return TRUE; | ||
1756 | 766 | } | 685 | } |
1757 | 767 | 686 | ||
1758 | 768 | gboolean | 687 | gboolean |
1759 | 769 | ubuntu_app_launch_observer_delete_app_resumed (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) | 688 | ubuntu_app_launch_observer_delete_app_resumed (UbuntuAppLaunchAppPausedResumedObserver observer, gpointer user_data) |
1760 | 770 | { | 689 | { |
1762 | 771 | return paused_resumed_delete(observer, user_data, &resumed_array); | 690 | auto iter = appResumedObservers.find(std::make_pair(observer, user_data)); |
1763 | 691 | |||
1764 | 692 | if (iter == appResumedObservers.end()) { | ||
1765 | 693 | return FALSE; | ||
1766 | 694 | } | ||
1767 | 695 | |||
1768 | 696 | appResumedObservers.erase(iter); | ||
1769 | 697 | return TRUE; | ||
1770 | 772 | } | 698 | } |
1771 | 773 | 699 | ||
1772 | 774 | typedef void (*per_instance_func_t) (GDBusConnection * con, GVariant * prop_dict, gpointer user_data); | 700 | typedef void (*per_instance_func_t) (GDBusConnection * con, GVariant * prop_dict, gpointer user_data); |
1773 | 775 | 701 | ||
1774 | === modified file 'tests/CMakeLists.txt' | |||
1775 | --- tests/CMakeLists.txt 2016-09-14 16:43:36 +0000 | |||
1776 | +++ tests/CMakeLists.txt 2016-11-07 20:56:13 +0000 | |||
1777 | @@ -157,6 +157,7 @@ | |||
1778 | 157 | 157 | ||
1779 | 158 | add_custom_target(format-tests | 158 | add_custom_target(format-tests |
1780 | 159 | COMMAND clang-format -i -style=file | 159 | COMMAND clang-format -i -style=file |
1781 | 160 | failure-test.cc | ||
1782 | 160 | application-info-desktop.cpp | 161 | application-info-desktop.cpp |
1783 | 161 | libual-cpp-test.cc | 162 | libual-cpp-test.cc |
1784 | 162 | list-apps.cpp | 163 | list-apps.cpp |
1785 | 163 | 164 | ||
1786 | === modified file 'tests/failure-test.cc' | |||
1787 | --- tests/failure-test.cc 2016-08-25 18:13:44 +0000 | |||
1788 | +++ tests/failure-test.cc 2016-11-07 20:56:13 +0000 | |||
1789 | @@ -17,120 +17,147 @@ | |||
1790 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
1791 | 18 | */ | 18 | */ |
1792 | 19 | 19 | ||
1793 | 20 | #include "eventually-fixture.h" | ||
1794 | 21 | #include "registry.h" | ||
1795 | 22 | #include <gio/gio.h> | ||
1796 | 23 | #include <glib/gstdio.h> | ||
1797 | 20 | #include <gtest/gtest.h> | 24 | #include <gtest/gtest.h> |
1798 | 21 | #include <glib/gstdio.h> | ||
1799 | 22 | #include <gio/gio.h> | ||
1800 | 23 | #include <ubuntu-app-launch.h> | ||
1801 | 24 | #include "eventually-fixture.h" | ||
1802 | 25 | 25 | ||
1803 | 26 | class FailureTest : public EventuallyFixture | 26 | class FailureTest : public EventuallyFixture |
1804 | 27 | { | 27 | { |
1818 | 28 | private: | 28 | private: |
1819 | 29 | GTestDBus * testbus = NULL; | 29 | GTestDBus* testbus = NULL; |
1820 | 30 | 30 | ||
1821 | 31 | protected: | 31 | protected: |
1822 | 32 | virtual void SetUp() { | 32 | std::shared_ptr<ubuntu::app_launch::Registry> registry; |
1823 | 33 | testbus = g_test_dbus_new(G_TEST_DBUS_NONE); | 33 | |
1824 | 34 | g_test_dbus_up(testbus); | 34 | virtual void SetUp() |
1825 | 35 | } | 35 | { |
1826 | 36 | 36 | /* Click DB test mode */ | |
1827 | 37 | virtual void TearDown() { | 37 | g_setenv("TEST_CLICK_DB", "click-db-dir", TRUE); |
1828 | 38 | g_test_dbus_down(testbus); | 38 | g_setenv("TEST_CLICK_USER", "test-user", TRUE); |
1829 | 39 | g_clear_object(&testbus); | 39 | |
1830 | 40 | } | 40 | gchar* linkfarmpath = g_build_filename(CMAKE_SOURCE_DIR, "link-farm", NULL); |
1831 | 41 | g_setenv("UBUNTU_APP_LAUNCH_LINK_FARM", linkfarmpath, TRUE); | ||
1832 | 42 | g_free(linkfarmpath); | ||
1833 | 43 | |||
1834 | 44 | g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE); | ||
1835 | 45 | g_setenv("XDG_CACHE_HOME", CMAKE_SOURCE_DIR "/libertine-data", TRUE); | ||
1836 | 46 | g_setenv("XDG_DATA_HOME", CMAKE_SOURCE_DIR "/libertine-home", TRUE); | ||
1837 | 47 | |||
1838 | 48 | testbus = g_test_dbus_new(G_TEST_DBUS_NONE); | ||
1839 | 49 | g_test_dbus_up(testbus); | ||
1840 | 50 | |||
1841 | 51 | registry = std::make_shared<ubuntu::app_launch::Registry>(); | ||
1842 | 52 | } | ||
1843 | 53 | |||
1844 | 54 | virtual void TearDown() | ||
1845 | 55 | { | ||
1846 | 56 | registry.reset(); | ||
1847 | 57 | |||
1848 | 58 | g_test_dbus_down(testbus); | ||
1849 | 59 | g_clear_object(&testbus); | ||
1850 | 60 | } | ||
1851 | 41 | }; | 61 | }; |
1852 | 42 | 62 | ||
1853 | 43 | static void | ||
1854 | 44 | failed_observer (const gchar * appid, UbuntuAppLaunchAppFailed reason, gpointer user_data) | ||
1855 | 45 | { | ||
1856 | 46 | if (reason == UBUNTU_APP_LAUNCH_APP_FAILED_CRASH) { | ||
1857 | 47 | std::string * last = static_cast<std::string *>(user_data); | ||
1858 | 48 | *last = appid; | ||
1859 | 49 | } | ||
1860 | 50 | } | ||
1861 | 51 | |||
1862 | 52 | TEST_F(FailureTest, CrashTest) | 63 | TEST_F(FailureTest, CrashTest) |
1863 | 53 | { | 64 | { |
1886 | 54 | g_setenv("EXIT_STATUS", "-100", TRUE); | 65 | g_setenv("EXIT_STATUS", "-100", TRUE); |
1887 | 55 | g_setenv("JOB", "application-click", TRUE); | 66 | g_setenv("JOB", "application-click", TRUE); |
1888 | 56 | g_setenv("INSTANCE", "foo", TRUE); | 67 | g_setenv("INSTANCE", "foo", TRUE); |
1889 | 57 | 68 | ||
1890 | 58 | std::string last_observer; | 69 | std::string last_observer; |
1891 | 59 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_failed(failed_observer, &last_observer)); | 70 | ubuntu::app_launch::Registry::appFailed(registry).connect( |
1892 | 60 | 71 | [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, | |
1893 | 61 | /* Status based */ | 72 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
1894 | 62 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | 73 | ubuntu::app_launch::Registry::FailureType type) { |
1895 | 63 | 74 | if (type == ubuntu::app_launch::Registry::FailureType::CRASH) | |
1896 | 64 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | 75 | { |
1897 | 65 | 76 | last_observer = app->appId(); | |
1898 | 66 | last_observer.clear(); | 77 | } |
1899 | 67 | g_unsetenv("EXIT_STATUS"); | 78 | }); |
1900 | 68 | g_setenv("EXIT_SIGNAL", "KILL", TRUE); | 79 | |
1901 | 69 | 80 | /* Status based */ | |
1902 | 70 | /* Signal based */ | 81 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
1903 | 71 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | 82 | |
1904 | 72 | 83 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | |
1905 | 73 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | 84 | |
1906 | 74 | 85 | last_observer.clear(); | |
1907 | 75 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_failed(failed_observer, &last_observer)); | 86 | g_unsetenv("EXIT_STATUS"); |
1908 | 87 | g_setenv("EXIT_SIGNAL", "KILL", TRUE); | ||
1909 | 88 | |||
1910 | 89 | /* Signal based */ | ||
1911 | 90 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | ||
1912 | 91 | |||
1913 | 92 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | ||
1914 | 76 | } | 93 | } |
1915 | 77 | 94 | ||
1916 | 78 | TEST_F(FailureTest, LegacyTest) | 95 | TEST_F(FailureTest, LegacyTest) |
1917 | 79 | { | 96 | { |
1931 | 80 | g_setenv("EXIT_STATUS", "-100", TRUE); | 97 | g_setenv("EXIT_STATUS", "-100", TRUE); |
1932 | 81 | g_setenv("JOB", "application-legacy", TRUE); | 98 | g_setenv("JOB", "application-legacy", TRUE); |
1933 | 82 | g_setenv("INSTANCE", "foo-1234", TRUE); | 99 | g_setenv("INSTANCE", "foo-1234", TRUE); |
1934 | 83 | 100 | ||
1935 | 84 | std::string last_observer; | 101 | std::string last_observer; |
1936 | 85 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_failed(failed_observer, &last_observer)); | 102 | ubuntu::app_launch::Registry::appFailed(registry).connect( |
1937 | 86 | 103 | [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, | |
1938 | 87 | /* Status based */ | 104 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
1939 | 88 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | 105 | ubuntu::app_launch::Registry::FailureType type) { |
1940 | 89 | 106 | g_debug("Signal handler called"); | |
1941 | 90 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | 107 | if (type == ubuntu::app_launch::Registry::FailureType::CRASH) |
1942 | 91 | 108 | { | |
1943 | 92 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_failed(failed_observer, &last_observer)); | 109 | last_observer = app->appId(); |
1944 | 110 | } | ||
1945 | 111 | }); | ||
1946 | 112 | |||
1947 | 113 | /* Status based */ | ||
1948 | 114 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | ||
1949 | 115 | |||
1950 | 116 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | ||
1951 | 93 | } | 117 | } |
1952 | 94 | 118 | ||
1953 | 95 | TEST_F(FailureTest, SnapTest) | 119 | TEST_F(FailureTest, SnapTest) |
1954 | 96 | { | 120 | { |
1977 | 97 | g_setenv("EXIT_STATUS", "-100", TRUE); | 121 | g_setenv("EXIT_STATUS", "-100", TRUE); |
1978 | 98 | g_setenv("JOB", "application-snap", TRUE); | 122 | g_setenv("JOB", "application-snap", TRUE); |
1979 | 99 | g_setenv("INSTANCE", "foo_bar_x123-1234", TRUE); | 123 | g_setenv("INSTANCE", "com.test.good_application_1.2.3-1234", TRUE); |
1980 | 100 | 124 | ||
1981 | 101 | std::string last_observer; | 125 | std::string last_observer; |
1982 | 102 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_failed(failed_observer, &last_observer)); | 126 | ubuntu::app_launch::Registry::appFailed(registry).connect( |
1983 | 103 | 127 | [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, | |
1984 | 104 | /* Status based */ | 128 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
1985 | 105 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | 129 | ubuntu::app_launch::Registry::FailureType type) { |
1986 | 106 | 130 | if (type == ubuntu::app_launch::Registry::FailureType::CRASH) | |
1987 | 107 | EXPECT_EVENTUALLY_EQ("foo_bar_x123", last_observer); | 131 | { |
1988 | 108 | 132 | last_observer = app->appId(); | |
1989 | 109 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_failed(failed_observer, &last_observer)); | 133 | } |
1990 | 110 | } | 134 | }); |
1991 | 111 | 135 | ||
1992 | 112 | static void | 136 | /* Status based */ |
1993 | 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)); |
1994 | 114 | { | 138 | |
1995 | 115 | if (reason == UBUNTU_APP_LAUNCH_APP_FAILED_START_FAILURE) { | 139 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", last_observer); |
1974 | 116 | std::string * last = static_cast<std::string *>(user_data); | ||
1975 | 117 | *last = appid; | ||
1976 | 118 | } | ||
1996 | 119 | } | 140 | } |
1997 | 120 | 141 | ||
1998 | 121 | TEST_F(FailureTest, StartTest) | 142 | TEST_F(FailureTest, StartTest) |
1999 | 122 | { | 143 | { |
2013 | 123 | g_setenv("JOB", "application-click", TRUE); | 144 | g_setenv("JOB", "application-click", TRUE); |
2014 | 124 | g_setenv("INSTANCE", "foo", TRUE); | 145 | g_setenv("INSTANCE", "foo", TRUE); |
2015 | 125 | g_unsetenv("EXIT_STATUS"); | 146 | g_unsetenv("EXIT_STATUS"); |
2016 | 126 | g_unsetenv("EXIT_SIGNAL"); | 147 | g_unsetenv("EXIT_SIGNAL"); |
2017 | 127 | 148 | ||
2018 | 128 | std::string last_observer; | 149 | std::string last_observer; |
2019 | 129 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_failed(failed_start_observer, &last_observer)); | 150 | ubuntu::app_launch::Registry::appFailed(registry).connect( |
2020 | 130 | 151 | [&last_observer](std::shared_ptr<ubuntu::app_launch::Application> app, | |
2021 | 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, |
2022 | 132 | 153 | ubuntu::app_launch::Registry::FailureType type) { | |
2023 | 133 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | 154 | if (type == ubuntu::app_launch::Registry::FailureType::START_FAILURE) |
2024 | 134 | 155 | { | |
2025 | 135 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_failed(failed_start_observer, &last_observer)); | 156 | last_observer = app->appId(); |
2026 | 157 | } | ||
2027 | 158 | }); | ||
2028 | 159 | |||
2029 | 160 | ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); | ||
2030 | 161 | |||
2031 | 162 | EXPECT_EVENTUALLY_EQ("foo", last_observer); | ||
2032 | 136 | } | 163 | } |
2033 | 137 | 164 | ||
2034 | === modified file 'tests/libual-cpp-test.cc' | |||
2035 | --- tests/libual-cpp-test.cc 2016-09-23 20:36:31 +0000 | |||
2036 | +++ tests/libual-cpp-test.cc 2016-11-07 20:56:13 +0000 | |||
2037 | @@ -49,32 +49,68 @@ | |||
2038 | 49 | DbusTestDbusMock* mock = NULL; | 49 | DbusTestDbusMock* mock = NULL; |
2039 | 50 | DbusTestDbusMock* cgmock = NULL; | 50 | DbusTestDbusMock* cgmock = NULL; |
2040 | 51 | GDBusConnection* bus = NULL; | 51 | GDBusConnection* bus = NULL; |
2041 | 52 | std::string last_focus_appid; | ||
2042 | 53 | std::string last_resume_appid; | ||
2043 | 54 | guint resume_timeout = 0; | 52 | guint resume_timeout = 0; |
2044 | 55 | std::shared_ptr<ubuntu::app_launch::Registry> registry; | 53 | std::shared_ptr<ubuntu::app_launch::Registry> registry; |
2045 | 56 | 54 | ||
2067 | 57 | private: | 55 | class ManagerMock : public ubuntu::app_launch::Registry::Manager |
2068 | 58 | static void focus_cb(const gchar* appid, gpointer user_data) | 56 | { |
2069 | 59 | { | 57 | GLib::ContextThread thread; |
2070 | 60 | g_debug("Focus Callback: %s", appid); | 58 | |
2071 | 61 | LibUAL* _this = static_cast<LibUAL*>(user_data); | 59 | public: |
2072 | 62 | _this->last_focus_appid = appid; | 60 | ManagerMock() |
2073 | 63 | } | 61 | { |
2074 | 64 | 62 | g_debug("Building a Manager Mock"); | |
2075 | 65 | static void resume_cb(const gchar* appid, gpointer user_data) | 63 | } |
2076 | 66 | { | 64 | |
2077 | 67 | g_debug("Resume Callback: %s", appid); | 65 | ~ManagerMock() |
2078 | 68 | LibUAL* _this = static_cast<LibUAL*>(user_data); | 66 | { |
2079 | 69 | _this->last_resume_appid = appid; | 67 | g_debug("Freeing a Manager Mock"); |
2080 | 70 | 68 | } | |
2081 | 71 | if (_this->resume_timeout > 0) | 69 | |
2082 | 72 | { | 70 | ubuntu::app_launch::AppID lastStartedApp; |
2083 | 73 | _this->pause(_this->resume_timeout); | 71 | ubuntu::app_launch::AppID lastFocusedApp; |
2084 | 74 | } | 72 | ubuntu::app_launch::AppID lastResumedApp; |
2085 | 75 | } | 73 | |
2086 | 76 | 74 | bool startingResponse{true}; | |
2087 | 77 | protected: | 75 | bool focusResponse{true}; |
2088 | 76 | bool resumeResponse{true}; | ||
2089 | 77 | |||
2090 | 78 | std::chrono::milliseconds startingTimeout{0}; | ||
2091 | 79 | std::chrono::milliseconds focusTimeout{0}; | ||
2092 | 80 | std::chrono::milliseconds resumeTimeout{0}; | ||
2093 | 81 | |||
2094 | 82 | void startingRequest(std::shared_ptr<ubuntu::app_launch::Application> app, | ||
2095 | 83 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, | ||
2096 | 84 | std::function<void(bool)> reply) override | ||
2097 | 85 | { | ||
2098 | 86 | thread.timeout(startingTimeout, [this, app, instance, reply]() { | ||
2099 | 87 | lastStartedApp = app->appId(); | ||
2100 | 88 | reply(startingResponse); | ||
2101 | 89 | }); | ||
2102 | 90 | } | ||
2103 | 91 | |||
2104 | 92 | void focusRequest(std::shared_ptr<ubuntu::app_launch::Application> app, | ||
2105 | 93 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, | ||
2106 | 94 | std::function<void(bool)> reply) override | ||
2107 | 95 | { | ||
2108 | 96 | thread.timeout(focusTimeout, [this, app, instance, reply]() { | ||
2109 | 97 | lastFocusedApp = app->appId(); | ||
2110 | 98 | reply(focusResponse); | ||
2111 | 99 | }); | ||
2112 | 100 | } | ||
2113 | 101 | |||
2114 | 102 | void resumeRequest(std::shared_ptr<ubuntu::app_launch::Application> app, | ||
2115 | 103 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, | ||
2116 | 104 | std::function<void(bool)> reply) override | ||
2117 | 105 | { | ||
2118 | 106 | thread.timeout(resumeTimeout, [this, app, instance, reply]() { | ||
2119 | 107 | lastResumedApp = app->appId(); | ||
2120 | 108 | reply(resumeResponse); | ||
2121 | 109 | }); | ||
2122 | 110 | } | ||
2123 | 111 | }; | ||
2124 | 112 | std::weak_ptr<ManagerMock> manager; | ||
2125 | 113 | |||
2126 | 78 | /* Useful debugging stuff, but not on by default. You really want to | 114 | /* Useful debugging stuff, but not on by default. You really want to |
2127 | 79 | not get all this noise typically */ | 115 | not get all this noise typically */ |
2128 | 80 | void debugConnection() | 116 | void debugConnection() |
2129 | @@ -127,13 +163,13 @@ | |||
2130 | 127 | 163 | ||
2131 | 128 | dbus_test_dbus_mock_object_add_method(mock, obj, "GetJobByName", G_VARIANT_TYPE("s"), G_VARIANT_TYPE("o"), | 164 | dbus_test_dbus_mock_object_add_method(mock, obj, "GetJobByName", G_VARIANT_TYPE("s"), G_VARIANT_TYPE("o"), |
2132 | 129 | "if args[0] == 'application-click':\n" | 165 | "if args[0] == 'application-click':\n" |
2134 | 130 | " ret = dbus.ObjectPath('/com/test/application_click')\n" | 166 | " ret = dbus.ObjectPath('/com/test/application_click')\n" |
2135 | 131 | "elif args[0] == 'application-snap':\n" | 167 | "elif args[0] == 'application-snap':\n" |
2137 | 132 | " ret = dbus.ObjectPath('/com/test/application_snap')\n" | 168 | " ret = dbus.ObjectPath('/com/test/application_snap')\n" |
2138 | 133 | "elif args[0] == 'application-legacy':\n" | 169 | "elif args[0] == 'application-legacy':\n" |
2140 | 134 | " ret = dbus.ObjectPath('/com/test/application_legacy')\n" | 170 | " ret = dbus.ObjectPath('/com/test/application_legacy')\n" |
2141 | 135 | "elif args[0] == 'untrusted-helper':\n" | 171 | "elif args[0] == 'untrusted-helper':\n" |
2143 | 136 | " ret = dbus.ObjectPath('/com/test/untrusted/helper')\n", | 172 | " ret = dbus.ObjectPath('/com/test/untrusted/helper')\n", |
2144 | 137 | NULL); | 173 | NULL); |
2145 | 138 | 174 | ||
2146 | 139 | dbus_test_dbus_mock_object_add_method(mock, obj, "SetEnv", G_VARIANT_TYPE("(assb)"), NULL, "", NULL); | 175 | dbus_test_dbus_mock_object_add_method(mock, obj, "SetEnv", G_VARIANT_TYPE("(assb)"), NULL, "", NULL); |
2147 | @@ -272,19 +308,23 @@ | |||
2148 | 272 | /* Make sure we pretend the CG manager is just on our bus */ | 308 | /* Make sure we pretend the CG manager is just on our bus */ |
2149 | 273 | g_setenv("UBUNTU_APP_LAUNCH_CG_MANAGER_SESSION_BUS", "YES", TRUE); | 309 | g_setenv("UBUNTU_APP_LAUNCH_CG_MANAGER_SESSION_BUS", "YES", TRUE); |
2150 | 274 | 310 | ||
2151 | 275 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_focus(focus_cb, this)); | ||
2152 | 276 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_resume(resume_cb, this)); | ||
2153 | 277 | |||
2154 | 278 | registry = std::make_shared<ubuntu::app_launch::Registry>(); | 311 | registry = std::make_shared<ubuntu::app_launch::Registry>(); |
2155 | 312 | |||
2156 | 313 | auto smanager = std::make_shared<ManagerMock>(); | ||
2157 | 314 | manager = smanager; | ||
2158 | 315 | ubuntu::app_launch::Registry::setManager(smanager, registry); | ||
2159 | 279 | } | 316 | } |
2160 | 280 | 317 | ||
2161 | 281 | virtual void TearDown() | 318 | virtual void TearDown() |
2162 | 282 | { | 319 | { |
2163 | 283 | ubuntu_app_launch_observer_delete_app_focus(focus_cb, this); | ||
2164 | 284 | ubuntu_app_launch_observer_delete_app_resume(resume_cb, this); | ||
2165 | 285 | |||
2166 | 286 | registry.reset(); | 320 | registry.reset(); |
2167 | 287 | 321 | ||
2168 | 322 | // NOTE: This should generally always be commented out, but | ||
2169 | 323 | // it is useful for debugging common errors, so leaving it | ||
2170 | 324 | // as a comment to make debugging those eaiser. | ||
2171 | 325 | // | ||
2172 | 326 | // ubuntu::app_launch::Registry::clearDefault(); | ||
2173 | 327 | |||
2174 | 288 | g_clear_object(&mock); | 328 | g_clear_object(&mock); |
2175 | 289 | g_clear_object(&cgmock); | 329 | g_clear_object(&cgmock); |
2176 | 290 | g_clear_object(&service); | 330 | g_clear_object(&service); |
2177 | @@ -793,33 +833,30 @@ | |||
2178 | 793 | #endif | 833 | #endif |
2179 | 794 | } | 834 | } |
2180 | 795 | 835 | ||
2181 | 796 | typedef struct | ||
2182 | 797 | { | ||
2183 | 798 | unsigned int count; | ||
2184 | 799 | const gchar* name; | ||
2185 | 800 | } observer_data_t; | ||
2186 | 801 | |||
2187 | 802 | static void observer_cb(const gchar* appid, gpointer user_data) | ||
2188 | 803 | { | ||
2189 | 804 | observer_data_t* data = (observer_data_t*)user_data; | ||
2190 | 805 | |||
2191 | 806 | if (data->name == NULL) | ||
2192 | 807 | { | ||
2193 | 808 | data->count++; | ||
2194 | 809 | } | ||
2195 | 810 | else if (g_strcmp0(data->name, appid) == 0) | ||
2196 | 811 | { | ||
2197 | 812 | data->count++; | ||
2198 | 813 | } | ||
2199 | 814 | } | ||
2200 | 815 | |||
2201 | 816 | TEST_F(LibUAL, StartStopObserver) | 836 | TEST_F(LibUAL, StartStopObserver) |
2202 | 817 | { | 837 | { |
2208 | 818 | observer_data_t start_data = {.count = 0, .name = nullptr}; | 838 | int start_count = 0; |
2209 | 819 | observer_data_t stop_data = {.count = 0, .name = nullptr}; | 839 | int stop_count = 0; |
2210 | 820 | 840 | ubuntu::app_launch::AppID start_appid; | |
2211 | 821 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_started(observer_cb, &start_data)); | 841 | ubuntu::app_launch::AppID stop_appid; |
2212 | 822 | ASSERT_TRUE(ubuntu_app_launch_observer_add_app_stop(observer_cb, &stop_data)); | 842 | |
2213 | 843 | ubuntu::app_launch::Registry::appStarted(registry).connect( | ||
2214 | 844 | [&start_count, &start_appid](std::shared_ptr<ubuntu::app_launch::Application> app, | ||
2215 | 845 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { | ||
2216 | 846 | if (!start_appid.empty() && !(start_appid == app->appId())) | ||
2217 | 847 | return; | ||
2218 | 848 | |||
2219 | 849 | start_count++; | ||
2220 | 850 | }); | ||
2221 | 851 | |||
2222 | 852 | ubuntu::app_launch::Registry::appStopped(registry).connect( | ||
2223 | 853 | [&stop_count, &stop_appid](std::shared_ptr<ubuntu::app_launch::Application> app, | ||
2224 | 854 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { | ||
2225 | 855 | if (!stop_appid.empty() && !(stop_appid == app->appId())) | ||
2226 | 856 | return; | ||
2227 | 857 | |||
2228 | 858 | stop_count++; | ||
2229 | 859 | }); | ||
2230 | 823 | 860 | ||
2231 | 824 | DbusTestDbusMockObject* obj = | 861 | DbusTestDbusMockObject* obj = |
2232 | 825 | dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); | 862 | dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); |
2233 | @@ -830,7 +867,7 @@ | |||
2234 | 830 | g_variant_new_parsed("('started', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), | 867 | g_variant_new_parsed("('started', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), |
2235 | 831 | NULL); | 868 | NULL); |
2236 | 832 | 869 | ||
2238 | 833 | EXPECT_EVENTUALLY_EQ(1, start_data.count); | 870 | EXPECT_EVENTUALLY_EQ(1, start_count); |
2239 | 834 | 871 | ||
2240 | 835 | /* Basic stop */ | 872 | /* Basic stop */ |
2241 | 836 | dbus_test_dbus_mock_object_emit_signal( | 873 | dbus_test_dbus_mock_object_emit_signal( |
2242 | @@ -838,33 +875,41 @@ | |||
2243 | 838 | g_variant_new_parsed("('stopped', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), | 875 | g_variant_new_parsed("('stopped', ['JOB=application-click', 'INSTANCE=com.test.good_application_1.2.3'])"), |
2244 | 839 | NULL); | 876 | NULL); |
2245 | 840 | 877 | ||
2247 | 841 | EXPECT_EVENTUALLY_EQ(1, stop_data.count); | 878 | EXPECT_EVENTUALLY_EQ(1, stop_count); |
2248 | 842 | 879 | ||
2249 | 843 | /* Start legacy */ | 880 | /* Start legacy */ |
2252 | 844 | start_data.count = 0; | 881 | start_count = 0; |
2253 | 845 | start_data.name = "multiple"; | 882 | start_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw({}), |
2254 | 883 | ubuntu::app_launch::AppID::AppName::from_raw("multiple"), | ||
2255 | 884 | ubuntu::app_launch::AppID::Version::from_raw({})}; | ||
2256 | 846 | 885 | ||
2257 | 847 | dbus_test_dbus_mock_object_emit_signal( | 886 | dbus_test_dbus_mock_object_emit_signal( |
2258 | 848 | mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), | 887 | mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
2259 | 849 | g_variant_new_parsed("('started', ['JOB=application-legacy', 'INSTANCE=multiple-234235'])"), NULL); | 888 | g_variant_new_parsed("('started', ['JOB=application-legacy', 'INSTANCE=multiple-234235'])"), NULL); |
2260 | 850 | 889 | ||
2262 | 851 | EXPECT_EVENTUALLY_EQ(1, start_data.count); | 890 | EXPECT_EVENTUALLY_EQ(1, start_count); |
2263 | 852 | 891 | ||
2264 | 853 | /* Legacy stop */ | 892 | /* Legacy stop */ |
2267 | 854 | stop_data.count = 0; | 893 | stop_count = 0; |
2268 | 855 | stop_data.name = "bar"; | 894 | stop_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw({}), |
2269 | 895 | ubuntu::app_launch::AppID::AppName::from_raw("foo"), | ||
2270 | 896 | ubuntu::app_launch::AppID::Version::from_raw({})}; | ||
2271 | 856 | 897 | ||
2272 | 857 | dbus_test_dbus_mock_object_emit_signal( | 898 | dbus_test_dbus_mock_object_emit_signal( |
2273 | 858 | mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), | 899 | mock, obj, "EventEmitted", G_VARIANT_TYPE("(sas)"), |
2275 | 859 | g_variant_new_parsed("('stopped', ['JOB=application-legacy', 'INSTANCE=bar-9344321'])"), NULL); | 900 | g_variant_new_parsed("('stopped', ['JOB=application-legacy', 'INSTANCE=foo-9344321'])"), NULL); |
2276 | 860 | 901 | ||
2278 | 861 | EXPECT_EVENTUALLY_EQ(1, stop_data.count); | 902 | EXPECT_EVENTUALLY_EQ(1, stop_count); |
2279 | 862 | 903 | ||
2280 | 863 | /* Test Noise Start */ | 904 | /* Test Noise Start */ |
2285 | 864 | start_data.count = 0; | 905 | start_count = 0; |
2286 | 865 | start_data.name = "com.test.good_application_1.2.3"; | 906 | start_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw("com.test.good"), |
2287 | 866 | stop_data.count = 0; | 907 | ubuntu::app_launch::AppID::AppName::from_raw("application"), |
2288 | 867 | stop_data.name = "com.test.good_application_1.2.3"; | 908 | ubuntu::app_launch::AppID::Version::from_raw("1.2.3")}; |
2289 | 909 | stop_count = 0; | ||
2290 | 910 | stop_appid = ubuntu::app_launch::AppID{ubuntu::app_launch::AppID::Package::from_raw("com.test.good"), | ||
2291 | 911 | ubuntu::app_launch::AppID::AppName::from_raw("application"), | ||
2292 | 912 | ubuntu::app_launch::AppID::Version::from_raw("1.2.3")}; | ||
2293 | 868 | 913 | ||
2294 | 869 | /* A full lifecycle */ | 914 | /* A full lifecycle */ |
2295 | 870 | dbus_test_dbus_mock_object_emit_signal( | 915 | dbus_test_dbus_mock_object_emit_signal( |
2296 | @@ -885,46 +930,33 @@ | |||
2297 | 885 | NULL); | 930 | NULL); |
2298 | 886 | 931 | ||
2299 | 887 | /* Ensure we just signaled once for each */ | 932 | /* Ensure we just signaled once for each */ |
2329 | 888 | EXPECT_EVENTUALLY_EQ(1, start_data.count); | 933 | EXPECT_EVENTUALLY_EQ(1, start_count); |
2330 | 889 | EXPECT_EVENTUALLY_EQ(1, stop_data.count); | 934 | EXPECT_EVENTUALLY_EQ(1, stop_count); |
2302 | 890 | |||
2303 | 891 | /* Remove */ | ||
2304 | 892 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_started(observer_cb, &start_data)); | ||
2305 | 893 | ASSERT_TRUE(ubuntu_app_launch_observer_delete_app_stop(observer_cb, &stop_data)); | ||
2306 | 894 | } | ||
2307 | 895 | |||
2308 | 896 | static GDBusMessage* filter_starting(GDBusConnection* conn, | ||
2309 | 897 | GDBusMessage* message, | ||
2310 | 898 | gboolean incomming, | ||
2311 | 899 | gpointer user_data) | ||
2312 | 900 | { | ||
2313 | 901 | if (g_strcmp0(g_dbus_message_get_member(message), "UnityStartingSignal") == 0) | ||
2314 | 902 | { | ||
2315 | 903 | unsigned int* count = static_cast<unsigned int*>(user_data); | ||
2316 | 904 | (*count)++; | ||
2317 | 905 | g_object_unref(message); | ||
2318 | 906 | return NULL; | ||
2319 | 907 | } | ||
2320 | 908 | |||
2321 | 909 | return message; | ||
2322 | 910 | } | ||
2323 | 911 | |||
2324 | 912 | static void starting_observer(const gchar* appid, gpointer user_data) | ||
2325 | 913 | { | ||
2326 | 914 | std::string* last = static_cast<std::string*>(user_data); | ||
2327 | 915 | *last = appid; | ||
2328 | 916 | return; | ||
2331 | 917 | } | 935 | } |
2332 | 918 | 936 | ||
2333 | 919 | TEST_F(LibUAL, StartingResponses) | 937 | TEST_F(LibUAL, StartingResponses) |
2334 | 920 | { | 938 | { |
2336 | 921 | std::string last_observer; | 939 | /* Get Bus */ |
2337 | 940 | GDBusConnection* session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | ||
2338 | 941 | |||
2339 | 942 | /* Setup filter to count signals out */ | ||
2340 | 922 | unsigned int starting_count = 0; | 943 | unsigned int starting_count = 0; |
2346 | 923 | GDBusConnection* session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | 944 | guint filter = g_dbus_connection_add_filter( |
2347 | 924 | guint filter = g_dbus_connection_add_filter(session, filter_starting, &starting_count, NULL); | 945 | session, |
2348 | 925 | 946 | [](GDBusConnection* conn, GDBusMessage* message, gboolean incomming, gpointer user_data) -> GDBusMessage* { | |
2349 | 926 | EXPECT_TRUE(ubuntu_app_launch_observer_add_app_starting(starting_observer, &last_observer)); | 947 | if (g_strcmp0(g_dbus_message_get_member(message), "UnityStartingSignal") == 0) |
2350 | 927 | 948 | { | |
2351 | 949 | unsigned int* count = static_cast<unsigned int*>(user_data); | ||
2352 | 950 | (*count)++; | ||
2353 | 951 | g_object_unref(message); | ||
2354 | 952 | return NULL; | ||
2355 | 953 | } | ||
2356 | 954 | |||
2357 | 955 | return message; | ||
2358 | 956 | }, | ||
2359 | 957 | &starting_count, NULL); | ||
2360 | 958 | |||
2361 | 959 | /* Emit a signal */ | ||
2362 | 928 | g_dbus_connection_emit_signal(session, NULL, /* destination */ | 960 | g_dbus_connection_emit_signal(session, NULL, /* destination */ |
2363 | 929 | "/", /* path */ | 961 | "/", /* path */ |
2364 | 930 | "com.canonical.UbuntuAppLaunch", /* interface */ | 962 | "com.canonical.UbuntuAppLaunch", /* interface */ |
2365 | @@ -932,11 +964,15 @@ | |||
2366 | 932 | g_variant_new("(s)", "com.test.good_application_1.2.3"), /* params, the same */ | 964 | g_variant_new("(s)", "com.test.good_application_1.2.3"), /* params, the same */ |
2367 | 933 | NULL); | 965 | NULL); |
2368 | 934 | 966 | ||
2370 | 935 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", last_observer); | 967 | /* Make sure we run our observer */ |
2371 | 968 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID(ubuntu::app_launch::AppID::Package::from_raw("com.test.good"), | ||
2372 | 969 | ubuntu::app_launch::AppID::AppName::from_raw("application"), | ||
2373 | 970 | ubuntu::app_launch::AppID::Version::from_raw("1.2.3")), | ||
2374 | 971 | manager.lock()->lastStartedApp); | ||
2375 | 972 | |||
2376 | 973 | /* Make sure we return */ | ||
2377 | 936 | EXPECT_EVENTUALLY_EQ(1, starting_count); | 974 | EXPECT_EVENTUALLY_EQ(1, starting_count); |
2378 | 937 | 975 | ||
2379 | 938 | EXPECT_TRUE(ubuntu_app_launch_observer_delete_app_starting(starting_observer, &last_observer)); | ||
2380 | 939 | |||
2381 | 940 | g_dbus_connection_remove_filter(session, filter); | 976 | g_dbus_connection_remove_filter(session, filter); |
2382 | 941 | g_object_unref(session); | 977 | g_object_unref(session); |
2383 | 942 | } | 978 | } |
2384 | @@ -947,8 +983,10 @@ | |||
2385 | 947 | auto app = ubuntu::app_launch::Application::create(appid, registry); | 983 | auto app = ubuntu::app_launch::Application::create(appid, registry); |
2386 | 948 | app->launch(); | 984 | app->launch(); |
2387 | 949 | 985 | ||
2390 | 950 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 986 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2391 | 951 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 987 | this->manager.lock()->lastFocusedApp); |
2392 | 988 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2393 | 989 | this->manager.lock()->lastResumedApp); | ||
2394 | 952 | } | 990 | } |
2395 | 953 | 991 | ||
2396 | 954 | GDBusMessage* filter_func_good(GDBusConnection* conn, GDBusMessage* message, gboolean incomming, gpointer user_data) | 992 | GDBusMessage* filter_func_good(GDBusConnection* conn, GDBusMessage* message, gboolean incomming, gpointer user_data) |
2397 | @@ -982,8 +1020,10 @@ | |||
2398 | 982 | 1020 | ||
2399 | 983 | app->launch(uris); | 1021 | app->launch(uris); |
2400 | 984 | 1022 | ||
2403 | 985 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 1023 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2404 | 986 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 1024 | this->manager.lock()->lastFocusedApp); |
2405 | 1025 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2406 | 1026 | this->manager.lock()->lastResumedApp); | ||
2407 | 987 | 1027 | ||
2408 | 988 | g_dbus_connection_remove_filter(session, filter); | 1028 | g_dbus_connection_remove_filter(session, filter); |
2409 | 989 | 1029 | ||
2410 | @@ -1015,8 +1055,10 @@ | |||
2411 | 1015 | 1055 | ||
2412 | 1016 | app->launch(uris); | 1056 | app->launch(uris); |
2413 | 1017 | 1057 | ||
2416 | 1018 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 1058 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2417 | 1019 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 1059 | this->manager.lock()->lastFocusedApp); |
2418 | 1060 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2419 | 1061 | this->manager.lock()->lastResumedApp); | ||
2420 | 1020 | } | 1062 | } |
2421 | 1021 | 1063 | ||
2422 | 1022 | TEST_F(LibUAL, UnityTimeoutTest) | 1064 | TEST_F(LibUAL, UnityTimeoutTest) |
2423 | @@ -1028,8 +1070,10 @@ | |||
2424 | 1028 | 1070 | ||
2425 | 1029 | app->launch(); | 1071 | app->launch(); |
2426 | 1030 | 1072 | ||
2429 | 1031 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 1073 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2430 | 1032 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 1074 | this->manager.lock()->lastResumedApp); |
2431 | 1075 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2432 | 1076 | this->manager.lock()->lastFocusedApp); | ||
2433 | 1033 | } | 1077 | } |
2434 | 1034 | 1078 | ||
2435 | 1035 | TEST_F(LibUAL, UnityTimeoutUriTest) | 1079 | TEST_F(LibUAL, UnityTimeoutUriTest) |
2436 | @@ -1043,8 +1087,10 @@ | |||
2437 | 1043 | 1087 | ||
2438 | 1044 | app->launch(uris); | 1088 | app->launch(uris); |
2439 | 1045 | 1089 | ||
2442 | 1046 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 1090 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2443 | 1047 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 1091 | this->manager.lock()->lastFocusedApp); |
2444 | 1092 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2445 | 1093 | this->manager.lock()->lastResumedApp); | ||
2446 | 1048 | } | 1094 | } |
2447 | 1049 | 1095 | ||
2448 | 1050 | GDBusMessage* filter_respawn(GDBusConnection* conn, GDBusMessage* message, gboolean incomming, gpointer user_data) | 1096 | GDBusMessage* filter_respawn(GDBusConnection* conn, GDBusMessage* message, gboolean incomming, gpointer user_data) |
2449 | @@ -1077,8 +1123,10 @@ | |||
2450 | 1077 | g_debug("Start call time: %d ms", (end - start) / 1000); | 1123 | g_debug("Start call time: %d ms", (end - start) / 1000); |
2451 | 1078 | EXPECT_LT(end - start, 2000 * 1000); | 1124 | EXPECT_LT(end - start, 2000 * 1000); |
2452 | 1079 | 1125 | ||
2455 | 1080 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_focus_appid); | 1126 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), |
2456 | 1081 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", this->last_resume_appid); | 1127 | this->manager.lock()->lastFocusedApp); |
2457 | 1128 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), | ||
2458 | 1129 | this->manager.lock()->lastResumedApp); | ||
2459 | 1082 | 1130 | ||
2460 | 1083 | g_dbus_connection_remove_filter(session, filter); | 1131 | g_dbus_connection_remove_filter(session, filter); |
2461 | 1084 | g_object_unref(session); | 1132 | g_object_unref(session); |
2462 | @@ -1138,23 +1186,21 @@ | |||
2463 | 1138 | g_variant_unref(env); | 1186 | g_variant_unref(env); |
2464 | 1139 | } | 1187 | } |
2465 | 1140 | 1188 | ||
2466 | 1141 | static void failed_observer(const gchar* appid, UbuntuAppLaunchAppFailed reason, gpointer user_data) | ||
2467 | 1142 | { | ||
2468 | 1143 | if (reason == UBUNTU_APP_LAUNCH_APP_FAILED_CRASH) | ||
2469 | 1144 | { | ||
2470 | 1145 | std::string* last = static_cast<std::string*>(user_data); | ||
2471 | 1146 | *last = appid; | ||
2472 | 1147 | } | ||
2473 | 1148 | return; | ||
2474 | 1149 | } | ||
2475 | 1150 | |||
2476 | 1151 | TEST_F(LibUAL, FailingObserver) | 1189 | TEST_F(LibUAL, FailingObserver) |
2477 | 1152 | { | 1190 | { |
2479 | 1153 | std::string last_observer; | 1191 | ubuntu::app_launch::AppID lastFailedApp; |
2480 | 1192 | ubuntu::app_launch::Registry::FailureType lastFailedType; | ||
2481 | 1193 | |||
2482 | 1194 | ubuntu::app_launch::Registry::appFailed(registry).connect( | ||
2483 | 1195 | [&lastFailedApp, &lastFailedType](std::shared_ptr<ubuntu::app_launch::Application> app, | ||
2484 | 1196 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, | ||
2485 | 1197 | ubuntu::app_launch::Registry::FailureType type) { | ||
2486 | 1198 | lastFailedApp = app->appId(); | ||
2487 | 1199 | lastFailedType = type; | ||
2488 | 1200 | }); | ||
2489 | 1201 | |||
2490 | 1154 | GDBusConnection* session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); | 1202 | GDBusConnection* session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2491 | 1155 | 1203 | ||
2492 | 1156 | EXPECT_TRUE(ubuntu_app_launch_observer_add_app_failed(failed_observer, &last_observer)); | ||
2493 | 1157 | |||
2494 | 1158 | g_dbus_connection_emit_signal( | 1204 | g_dbus_connection_emit_signal( |
2495 | 1159 | session, NULL, /* destination */ | 1205 | session, NULL, /* destination */ |
2496 | 1160 | "/", /* path */ | 1206 | "/", /* path */ |
2497 | @@ -1163,9 +1209,10 @@ | |||
2498 | 1163 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "crash"), /* params, the same */ | 1209 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "crash"), /* params, the same */ |
2499 | 1164 | NULL); | 1210 | NULL); |
2500 | 1165 | 1211 | ||
2502 | 1166 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", last_observer); | 1212 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), lastFailedApp); |
2503 | 1213 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::Registry::FailureType::CRASH, lastFailedType); | ||
2504 | 1167 | 1214 | ||
2506 | 1168 | last_observer.clear(); | 1215 | lastFailedApp = ubuntu::app_launch::AppID(); |
2507 | 1169 | 1216 | ||
2508 | 1170 | g_dbus_connection_emit_signal( | 1217 | g_dbus_connection_emit_signal( |
2509 | 1171 | session, NULL, /* destination */ | 1218 | session, NULL, /* destination */ |
2510 | @@ -1175,9 +1222,9 @@ | |||
2511 | 1175 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "blahblah"), /* params, the same */ | 1222 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "blahblah"), /* params, the same */ |
2512 | 1176 | NULL); | 1223 | NULL); |
2513 | 1177 | 1224 | ||
2515 | 1178 | EXPECT_EVENTUALLY_EQ("com.test.good_application_1.2.3", last_observer); | 1225 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::AppID::parse("com.test.good_application_1.2.3"), lastFailedApp); |
2516 | 1179 | 1226 | ||
2518 | 1180 | last_observer.clear(); | 1227 | lastFailedApp = ubuntu::app_launch::AppID(); |
2519 | 1181 | 1228 | ||
2520 | 1182 | g_dbus_connection_emit_signal( | 1229 | g_dbus_connection_emit_signal( |
2521 | 1183 | session, NULL, /* destination */ | 1230 | session, NULL, /* destination */ |
2522 | @@ -1187,9 +1234,7 @@ | |||
2523 | 1187 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "start-failure"), /* params, the same */ | 1234 | g_variant_new("(ss)", "com.test.good_application_1.2.3", "start-failure"), /* params, the same */ |
2524 | 1188 | NULL); | 1235 | NULL); |
2525 | 1189 | 1236 | ||
2529 | 1190 | EXPECT_EVENTUALLY_EQ(true, last_observer.empty()); | 1237 | EXPECT_EVENTUALLY_EQ(ubuntu::app_launch::Registry::FailureType::START_FAILURE, lastFailedType); |
2527 | 1191 | |||
2528 | 1192 | EXPECT_TRUE(ubuntu_app_launch_observer_delete_app_failed(failed_observer, &last_observer)); | ||
2530 | 1193 | 1238 | ||
2531 | 1194 | g_object_unref(session); | 1239 | g_object_unref(session); |
2532 | 1195 | } | 1240 | } |
2533 | 1196 | 1241 | ||
2534 | === modified file 'tools/CMakeLists.txt' | |||
2535 | --- tools/CMakeLists.txt 2016-06-18 18:24:27 +0000 | |||
2536 | +++ tools/CMakeLists.txt 2016-11-07 20:56:13 +0000 | |||
2537 | @@ -39,7 +39,7 @@ | |||
2538 | 39 | # ubuntu-app-launch | 39 | # ubuntu-app-launch |
2539 | 40 | ######################## | 40 | ######################## |
2540 | 41 | 41 | ||
2542 | 42 | add_executable(ubuntu-app-launch ubuntu-app-launch.c) | 42 | add_executable(ubuntu-app-launch ubuntu-app-launch.cpp) |
2543 | 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") |
2544 | 44 | target_link_libraries(ubuntu-app-launch ubuntu-launcher) | 44 | target_link_libraries(ubuntu-app-launch ubuntu-launcher) |
2545 | 45 | install(TARGETS ubuntu-app-launch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") | 45 | install(TARGETS ubuntu-app-launch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
2546 | @@ -48,7 +48,7 @@ | |||
2547 | 48 | # ubuntu-app-watch | 48 | # ubuntu-app-watch |
2548 | 49 | ######################## | 49 | ######################## |
2549 | 50 | 50 | ||
2551 | 51 | add_executable(ubuntu-app-watch ubuntu-app-watch.c) | 51 | add_executable(ubuntu-app-watch ubuntu-app-watch.cpp) |
2552 | 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") |
2553 | 53 | target_link_libraries(ubuntu-app-watch ubuntu-launcher) | 53 | target_link_libraries(ubuntu-app-watch ubuntu-launcher) |
2554 | 54 | install(TARGETS ubuntu-app-watch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") | 54 | install(TARGETS ubuntu-app-watch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
2555 | @@ -116,3 +116,22 @@ | |||
2556 | 116 | target_link_libraries(ubuntu-app-usage ubuntu-launcher) | 116 | target_link_libraries(ubuntu-app-usage ubuntu-launcher) |
2557 | 117 | install(TARGETS ubuntu-app-usage RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") | 117 | install(TARGETS ubuntu-app-usage RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
2558 | 118 | 118 | ||
2559 | 119 | ######################## | ||
2560 | 120 | # Formatting | ||
2561 | 121 | ######################## | ||
2562 | 122 | |||
2563 | 123 | add_custom_target(format-tools | ||
2564 | 124 | COMMAND clang-format -i -style=file | ||
2565 | 125 | ubuntu-app-info.cpp | ||
2566 | 126 | ubuntu-app-launch-appids.cpp | ||
2567 | 127 | ubuntu-app-launch.cpp | ||
2568 | 128 | ubuntu-app-list.cpp | ||
2569 | 129 | ubuntu-app-list-pids.cpp | ||
2570 | 130 | ubuntu-app-pid.cpp | ||
2571 | 131 | ubuntu-app-stop.cpp | ||
2572 | 132 | ubuntu-app-triplet.cpp | ||
2573 | 133 | ubuntu-app-watch.cpp | ||
2574 | 134 | ubuntu-helper-list.cpp | ||
2575 | 135 | ubuntu-helper-start.cpp | ||
2576 | 136 | ubuntu-helper-stop.cpp | ||
2577 | 137 | ) | ||
2578 | 119 | 138 | ||
2579 | === modified file 'tools/ubuntu-app-info.cpp' | |||
2580 | --- tools/ubuntu-app-info.cpp 2016-05-04 14:09:10 +0000 | |||
2581 | +++ tools/ubuntu-app-info.cpp 2016-11-07 20:56:13 +0000 | |||
2582 | @@ -17,34 +17,40 @@ | |||
2583 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
2584 | 18 | */ | 18 | */ |
2585 | 19 | 19 | ||
2586 | 20 | #include <iostream> | ||
2587 | 21 | #include "libubuntu-app-launch/application.h" | 20 | #include "libubuntu-app-launch/application.h" |
2588 | 22 | #include "libubuntu-app-launch/registry.h" | 21 | #include "libubuntu-app-launch/registry.h" |
2589 | 22 | #include <iostream> | ||
2590 | 23 | 23 | ||
2592 | 24 | int main(int argc, char* argv[]) | 24 | int main(int argc, char *argv[]) |
2593 | 25 | { | 25 | { |
2595 | 26 | if (argc != 2) { | 26 | if (argc != 2) |
2596 | 27 | { | ||
2597 | 27 | std::cerr << "Usage: " << argv[0] << " (appid)" << std::endl; | 28 | std::cerr << "Usage: " << argv[0] << " (appid)" << std::endl; |
2598 | 28 | exit(1); | 29 | exit(1); |
2599 | 29 | } | 30 | } |
2600 | 30 | 31 | ||
2601 | 31 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); | 32 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); |
2603 | 32 | if (appid.empty()) { | 33 | if (appid.empty()) |
2604 | 34 | { | ||
2605 | 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; |
2606 | 34 | return 1; | 36 | return 1; |
2607 | 35 | } | 37 | } |
2608 | 36 | 38 | ||
2609 | 37 | std::shared_ptr<ubuntu::app_launch::Application> app; | 39 | std::shared_ptr<ubuntu::app_launch::Application> app; |
2611 | 38 | try { | 40 | try |
2612 | 41 | { | ||
2613 | 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()); |
2614 | 40 | if (!app) | 43 | if (!app) |
2615 | 41 | throw std::runtime_error("Application object is nullptr"); | 44 | throw std::runtime_error("Application object is nullptr"); |
2617 | 42 | } catch (std::runtime_error &e) { | 45 | } |
2618 | 46 | catch (std::runtime_error &e) | ||
2619 | 47 | { | ||
2620 | 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; |
2621 | 44 | exit(1); | 49 | exit(1); |
2622 | 45 | } | 50 | } |
2623 | 46 | 51 | ||
2625 | 47 | try { | 52 | try |
2626 | 53 | { | ||
2627 | 48 | auto info = app->info(); | 54 | auto info = app->info(); |
2628 | 49 | 55 | ||
2629 | 50 | std::cout << "Name: " << info->name().value() << std::endl; | 56 | std::cout << "Name: " << info->name().value() << std::endl; |
2630 | @@ -64,8 +70,11 @@ | |||
2631 | 64 | std::cout << " Inv Landscape: " << info->supportedOrientations().invertedLandscape << std::endl; | 70 | std::cout << " Inv Landscape: " << info->supportedOrientations().invertedLandscape << std::endl; |
2632 | 65 | std::cout << "Rotates: " << info->rotatesWindowContents().value() << std::endl; | 71 | std::cout << "Rotates: " << info->rotatesWindowContents().value() << std::endl; |
2633 | 66 | std::cout << "Ubuntu Lifecycle: " << info->supportsUbuntuLifecycle().value() << std::endl; | 72 | std::cout << "Ubuntu Lifecycle: " << info->supportsUbuntuLifecycle().value() << std::endl; |
2636 | 67 | } catch (std::runtime_error &e) { | 73 | } |
2637 | 68 | std::cerr << "Unable to parse Application info for application '" << std::string(appid) << "': " << e.what() << std::endl; | 74 | catch (std::runtime_error &e) |
2638 | 75 | { | ||
2639 | 76 | std::cerr << "Unable to parse Application info for application '" << std::string(appid) << "': " << e.what() | ||
2640 | 77 | << std::endl; | ||
2641 | 69 | exit(1); | 78 | exit(1); |
2642 | 70 | } | 79 | } |
2643 | 71 | 80 | ||
2644 | 72 | 81 | ||
2645 | === renamed file 'tools/ubuntu-app-launch.c' => 'tools/ubuntu-app-launch.cpp' | |||
2646 | --- tools/ubuntu-app-launch.c 2016-02-08 19:03:31 +0000 | |||
2647 | +++ tools/ubuntu-app-launch.cpp 2016-11-07 20:56:13 +0000 | |||
2648 | @@ -1,5 +1,5 @@ | |||
2649 | 1 | /* | 1 | /* |
2651 | 2 | * Copyright 2013 Canonical Ltd. | 2 | * Copyright © 2016 Canonical Ltd. |
2652 | 3 | * | 3 | * |
2653 | 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 |
2654 | 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 |
2655 | @@ -17,71 +17,59 @@ | |||
2656 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
2657 | 18 | */ | 18 | */ |
2658 | 19 | 19 | ||
2726 | 20 | #include <glib.h> | 20 | #include "libubuntu-app-launch/application.h" |
2727 | 21 | #include "libubuntu-app-launch/ubuntu-app-launch.h" | 21 | #include "libubuntu-app-launch/registry.h" |
2728 | 22 | 22 | #include <csignal> | |
2729 | 23 | const gchar * global_appid = NULL; | 23 | #include <future> |
2730 | 24 | int retval = 0; | 24 | #include <iostream> |
2731 | 25 | 25 | ||
2732 | 26 | static void | 26 | ubuntu::app_launch::AppID global_appid; |
2733 | 27 | good_observer (const gchar * appid, gpointer user_data) | 27 | std::promise<int> retval; |
2734 | 28 | { | 28 | |
2735 | 29 | if (g_strcmp0(appid, global_appid) != 0) { | 29 | int main(int argc, char* argv[]) |
2736 | 30 | return; | 30 | { |
2737 | 31 | } | 31 | if (argc < 2) |
2738 | 32 | 32 | { | |
2739 | 33 | g_debug("Application '%s' running", appid); | 33 | std::cerr << "Usage: " << argv[0] << " <app id> [uris]" << std::endl; |
2740 | 34 | g_main_loop_quit((GMainLoop *)user_data); | 34 | return 1; |
2741 | 35 | } | 35 | } |
2742 | 36 | 36 | ||
2743 | 37 | static void | 37 | global_appid = ubuntu::app_launch::AppID::find(argv[1]); |
2744 | 38 | bad_observer (const gchar * appid, UbuntuAppLaunchAppFailed failure_type, gpointer user_data) | 38 | |
2745 | 39 | { | 39 | std::vector<ubuntu::app_launch::Application::URL> urls; |
2746 | 40 | if (g_strcmp0(appid, global_appid) != 0) { | 40 | for (int i = 2; i < argc; i++) |
2747 | 41 | return; | 41 | { |
2748 | 42 | } | 42 | urls.push_back(ubuntu::app_launch::Application::URL::from_raw(argv[i])); |
2749 | 43 | 43 | } | |
2750 | 44 | g_debug("Application '%s' failed: %s", appid, failure_type == UBUNTU_APP_LAUNCH_APP_FAILED_CRASH ? "crash" : "startup failure"); | 44 | |
2751 | 45 | retval = -1; | 45 | ubuntu::app_launch::Registry::appStarted().connect( |
2752 | 46 | g_main_loop_quit((GMainLoop *)user_data); | 46 | [](std::shared_ptr<ubuntu::app_launch::Application> app, |
2753 | 47 | } | 47 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { |
2754 | 48 | 48 | if (app->appId() != global_appid) | |
2755 | 49 | int | 49 | { |
2756 | 50 | main (int argc, gchar * argv[]) { | 50 | return; |
2757 | 51 | if (argc < 2) { | 51 | } |
2758 | 52 | g_printerr("Usage: %s <app id> [uris]\n", argv[0]); | 52 | |
2759 | 53 | return 1; | 53 | std::cout << "Started: " << (std::string)app->appId() << std::endl; |
2760 | 54 | } | 54 | retval.set_value(EXIT_SUCCESS); |
2761 | 55 | 55 | }); | |
2762 | 56 | global_appid = argv[1]; | 56 | |
2763 | 57 | GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); | 57 | ubuntu::app_launch::Registry::appFailed().connect( |
2764 | 58 | 58 | [](std::shared_ptr<ubuntu::app_launch::Application> app, | |
2765 | 59 | gchar ** uris = NULL; | 59 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
2766 | 60 | if (argc > 2) { | 60 | ubuntu::app_launch::Registry::FailureType type) { |
2767 | 61 | int i; | 61 | if (app->appId() != global_appid) |
2768 | 62 | 62 | { | |
2769 | 63 | uris = g_new0(gchar *, argc - 1); | 63 | return; |
2770 | 64 | 64 | } | |
2771 | 65 | for (i = 2; i < argc; i++) { | 65 | |
2772 | 66 | uris[i - 2] = argv[i]; | 66 | std::cout << "Failed: " << (std::string)app->appId() << std::endl; |
2773 | 67 | } | 67 | retval.set_value(EXIT_FAILURE); |
2774 | 68 | } | 68 | }); |
2775 | 69 | 69 | ||
2776 | 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()); |
2777 | 71 | ubuntu_app_launch_observer_add_app_focus(good_observer, mainloop); | 71 | app->launch(urls); |
2778 | 72 | 72 | ||
2779 | 73 | ubuntu_app_launch_observer_add_app_failed(bad_observer, mainloop); | 73 | std::signal(SIGTERM, [](int signal) -> void { retval.set_value(EXIT_SUCCESS); }); |
2780 | 74 | 74 | return retval.get_future().get(); | |
2714 | 75 | ubuntu_app_launch_start_application(global_appid, (const gchar * const *)uris); | ||
2715 | 76 | |||
2716 | 77 | g_main_loop_run(mainloop); | ||
2717 | 78 | |||
2718 | 79 | ubuntu_app_launch_observer_delete_app_started(good_observer, mainloop); | ||
2719 | 80 | ubuntu_app_launch_observer_delete_app_focus(good_observer, mainloop); | ||
2720 | 81 | ubuntu_app_launch_observer_delete_app_failed(bad_observer, mainloop); | ||
2721 | 82 | |||
2722 | 83 | g_main_loop_unref(mainloop); | ||
2723 | 84 | g_free(uris); | ||
2724 | 85 | |||
2725 | 86 | return retval; | ||
2781 | 87 | } | 75 | } |
2782 | 88 | 76 | ||
2783 | === modified file 'tools/ubuntu-app-list-pids.cpp' | |||
2784 | --- tools/ubuntu-app-list-pids.cpp 2016-05-03 01:46:27 +0000 | |||
2785 | +++ tools/ubuntu-app-list-pids.cpp 2016-11-07 20:56:13 +0000 | |||
2786 | @@ -30,12 +30,14 @@ | |||
2787 | 30 | } | 30 | } |
2788 | 31 | 31 | ||
2789 | 32 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); | 32 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); |
2791 | 33 | if (appid.empty()) { | 33 | if (appid.empty()) |
2792 | 34 | { | ||
2793 | 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; |
2794 | 35 | return 1; | 36 | return 1; |
2795 | 36 | } | 37 | } |
2796 | 37 | 38 | ||
2798 | 38 | try { | 39 | try |
2799 | 40 | { | ||
2800 | 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()); |
2801 | 40 | 42 | ||
2802 | 41 | for (auto instance : app->instances()) | 43 | for (auto instance : app->instances()) |
2803 | @@ -45,7 +47,9 @@ | |||
2804 | 45 | std::cout << pid << std::endl; | 47 | std::cout << pid << std::endl; |
2805 | 46 | } | 48 | } |
2806 | 47 | } | 49 | } |
2808 | 48 | } catch (std::runtime_error &e) { | 50 | } |
2809 | 51 | catch (std::runtime_error& e) | ||
2810 | 52 | { | ||
2811 | 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; |
2812 | 50 | return 1; | 54 | return 1; |
2813 | 51 | } | 55 | } |
2814 | 52 | 56 | ||
2815 | === modified file 'tools/ubuntu-app-list.cpp' | |||
2816 | --- tools/ubuntu-app-list.cpp 2016-02-09 21:12:54 +0000 | |||
2817 | +++ tools/ubuntu-app-list.cpp 2016-11-07 20:56:13 +0000 | |||
2818 | @@ -17,8 +17,8 @@ | |||
2819 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
2820 | 18 | */ | 18 | */ |
2821 | 19 | 19 | ||
2822 | 20 | #include "libubuntu-app-launch/registry.h" | ||
2823 | 20 | #include <iostream> | 21 | #include <iostream> |
2824 | 21 | #include "libubuntu-app-launch/registry.h" | ||
2825 | 22 | 22 | ||
2826 | 23 | int main(int argc, char* argv[]) | 23 | int main(int argc, char* argv[]) |
2827 | 24 | { | 24 | { |
2828 | 25 | 25 | ||
2829 | === modified file 'tools/ubuntu-app-pid.cpp' | |||
2830 | --- tools/ubuntu-app-pid.cpp 2016-05-03 01:46:51 +0000 | |||
2831 | +++ tools/ubuntu-app-pid.cpp 2016-11-07 20:56:13 +0000 | |||
2832 | @@ -18,8 +18,8 @@ | |||
2833 | 18 | */ | 18 | */ |
2834 | 19 | 19 | ||
2835 | 20 | #include <iostream> | 20 | #include <iostream> |
2836 | 21 | #include <libubuntu-app-launch/application.h> | ||
2837 | 21 | #include <libubuntu-app-launch/registry.h> | 22 | #include <libubuntu-app-launch/registry.h> |
2838 | 22 | #include <libubuntu-app-launch/application.h> | ||
2839 | 23 | 23 | ||
2840 | 24 | int main(int argc, char* argv[]) | 24 | int main(int argc, char* argv[]) |
2841 | 25 | { | 25 | { |
2842 | @@ -31,12 +31,14 @@ | |||
2843 | 31 | } | 31 | } |
2844 | 32 | 32 | ||
2845 | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); |
2847 | 34 | if (appid.empty()) { | 34 | if (appid.empty()) |
2848 | 35 | { | ||
2849 | 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; |
2850 | 36 | return 1; | 37 | return 1; |
2851 | 37 | } | 38 | } |
2852 | 38 | 39 | ||
2854 | 39 | try { | 40 | try |
2855 | 41 | { | ||
2856 | 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()); |
2857 | 41 | auto pid = app->instances()[0]->primaryPid(); | 43 | auto pid = app->instances()[0]->primaryPid(); |
2858 | 42 | 44 | ||
2859 | @@ -47,7 +49,9 @@ | |||
2860 | 47 | 49 | ||
2861 | 48 | std::cout << pid << std::endl; | 50 | std::cout << pid << std::endl; |
2862 | 49 | return 0; | 51 | return 0; |
2864 | 50 | } catch (std::runtime_error &e) { | 52 | } |
2865 | 53 | catch (std::runtime_error& e) | ||
2866 | 54 | { | ||
2867 | 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; |
2868 | 52 | return 1; | 56 | return 1; |
2869 | 53 | } | 57 | } |
2870 | 54 | 58 | ||
2871 | === modified file 'tools/ubuntu-app-stop.cpp' | |||
2872 | --- tools/ubuntu-app-stop.cpp 2016-05-03 01:46:27 +0000 | |||
2873 | +++ tools/ubuntu-app-stop.cpp 2016-11-07 20:56:13 +0000 | |||
2874 | @@ -30,19 +30,23 @@ | |||
2875 | 30 | } | 30 | } |
2876 | 31 | 31 | ||
2877 | 32 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); | 32 | auto appid = ubuntu::app_launch::AppID::find(argv[1]); |
2879 | 33 | if (appid.empty()) { | 33 | if (appid.empty()) |
2880 | 34 | { | ||
2881 | 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; |
2882 | 35 | return 1; | 36 | return 1; |
2883 | 36 | } | 37 | } |
2884 | 37 | 38 | ||
2886 | 38 | try { | 39 | try |
2887 | 40 | { | ||
2888 | 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()); |
2889 | 40 | 42 | ||
2890 | 41 | for (auto instance : app->instances()) | 43 | for (auto instance : app->instances()) |
2891 | 42 | { | 44 | { |
2892 | 43 | instance->stop(); | 45 | instance->stop(); |
2893 | 44 | } | 46 | } |
2895 | 45 | } catch (std::runtime_error &e) { | 47 | } |
2896 | 48 | catch (std::runtime_error& e) | ||
2897 | 49 | { | ||
2898 | 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; |
2899 | 47 | return 1; | 51 | return 1; |
2900 | 48 | } | 52 | } |
2901 | 49 | 53 | ||
2902 | === modified file 'tools/ubuntu-app-triplet.cpp' | |||
2903 | --- tools/ubuntu-app-triplet.cpp 2016-02-09 21:12:54 +0000 | |||
2904 | +++ tools/ubuntu-app-triplet.cpp 2016-11-07 20:56:13 +0000 | |||
2905 | @@ -17,8 +17,8 @@ | |||
2906 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
2907 | 18 | */ | 18 | */ |
2908 | 19 | 19 | ||
2909 | 20 | #include "libubuntu-app-launch/application.h" | ||
2910 | 20 | #include <iostream> | 21 | #include <iostream> |
2911 | 21 | #include "libubuntu-app-launch/application.h" | ||
2912 | 22 | 22 | ||
2913 | 23 | int main(int argc, char* argv[]) | 23 | int main(int argc, char* argv[]) |
2914 | 24 | { | 24 | { |
2915 | 25 | 25 | ||
2916 | === renamed file 'tools/ubuntu-app-watch.c' => 'tools/ubuntu-app-watch.cpp' | |||
2917 | --- tools/ubuntu-app-watch.c 2016-02-08 19:03:31 +0000 | |||
2918 | +++ tools/ubuntu-app-watch.cpp 2016-11-07 20:56:13 +0000 | |||
2919 | @@ -1,5 +1,5 @@ | |||
2920 | 1 | /* | 1 | /* |
2922 | 2 | * Copyright 2013 Canonical Ltd. | 2 | * Copyright © 2015 Canonical Ltd. |
2923 | 3 | * | 3 | * |
2924 | 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 |
2925 | 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 |
2926 | @@ -17,91 +17,64 @@ | |||
2927 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
2928 | 18 | */ | 18 | */ |
2929 | 19 | 19 | ||
3017 | 20 | #include "libubuntu-app-launch/ubuntu-app-launch.h" | 20 | #include "libubuntu-app-launch/registry.h" |
3018 | 21 | 21 | #include <csignal> | |
3019 | 22 | void | 22 | #include <future> |
3020 | 23 | starting (const gchar * appid, gpointer user_data) | 23 | |
3021 | 24 | { | 24 | std::promise<int> retval; |
3022 | 25 | g_print("Starting %s\n", appid); | 25 | |
3023 | 26 | return; | 26 | int main(int argc, char *argv[]) |
3024 | 27 | } | 27 | { |
3025 | 28 | 28 | ubuntu::app_launch::Registry registry; | |
3026 | 29 | void | 29 | |
3027 | 30 | started (const gchar * appid, gpointer user_data) | 30 | registry.appStarted().connect([](std::shared_ptr<ubuntu::app_launch::Application> app, |
3028 | 31 | { | 31 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { |
3029 | 32 | g_print("Started %s\n", appid); | 32 | std::cout << "Started: " << (std::string)app->appId() << std::endl; |
3030 | 33 | return; | 33 | }); |
3031 | 34 | } | 34 | registry.appStopped().connect([](std::shared_ptr<ubuntu::app_launch::Application> app, |
3032 | 35 | 35 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance) { | |
3033 | 36 | void | 36 | std::cout << "Stopped: " << (std::string)app->appId() << std::endl; |
3034 | 37 | stopped (const gchar * appid, gpointer user_data) | 37 | }); |
3035 | 38 | { | 38 | registry.appPaused().connect([](std::shared_ptr<ubuntu::app_launch::Application> app, |
3036 | 39 | g_print("Stop %s\n", appid); | 39 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
3037 | 40 | return; | 40 | std::vector<pid_t> &pids) { |
3038 | 41 | } | 41 | std::cout << "Paused: " << (std::string)app->appId() << " ("; |
3039 | 42 | 42 | ||
3040 | 43 | void | 43 | for (auto pid : pids) |
3041 | 44 | resumed (const gchar * appid, GPid * pids, gpointer user_data) | 44 | { |
3042 | 45 | { | 45 | std::cout << std::to_string(pid) << " "; |
3043 | 46 | g_print("Resumed %s\n", appid); | 46 | } |
3044 | 47 | return; | 47 | |
3045 | 48 | } | 48 | std::cout << ")" << std::endl; |
3046 | 49 | 49 | }); | |
3047 | 50 | void | 50 | registry.appResumed().connect([](std::shared_ptr<ubuntu::app_launch::Application> app, |
3048 | 51 | paused (const gchar * appid, GPid * pids, gpointer user_data) | 51 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, |
3049 | 52 | { | 52 | std::vector<pid_t> &pids) { |
3050 | 53 | g_print("Paused %s\n", appid); | 53 | std::cout << "Resumed: " << (std::string)app->appId() << " ("; |
3051 | 54 | return; | 54 | |
3052 | 55 | } | 55 | for (auto pid : pids) |
3053 | 56 | 56 | { | |
3054 | 57 | void | 57 | std::cout << std::to_string(pid) << " "; |
3055 | 58 | focus (const gchar * appid, gpointer user_data) | 58 | } |
3056 | 59 | { | 59 | |
3057 | 60 | g_print("Focus %s\n", appid); | 60 | std::cout << ")" << std::endl; |
3058 | 61 | return; | 61 | }); |
3059 | 62 | } | 62 | registry.appFailed().connect([](std::shared_ptr<ubuntu::app_launch::Application> app, |
3060 | 63 | 63 | std::shared_ptr<ubuntu::app_launch::Application::Instance> instance, | |
3061 | 64 | void | 64 | ubuntu::app_launch::Registry::FailureType type) { |
3062 | 65 | fail (const gchar * appid, UbuntuAppLaunchAppFailed failhow, gpointer user_data) | 65 | std::cout << "Failed: " << (std::string)app->appId(); |
3063 | 66 | { | 66 | switch (type) |
3064 | 67 | const gchar * failstr = "unknown"; | 67 | { |
3065 | 68 | switch (failhow) { | 68 | case ubuntu::app_launch::Registry::FailureType::CRASH: |
3066 | 69 | case UBUNTU_APP_LAUNCH_APP_FAILED_CRASH: | 69 | std::cout << " (crash)"; |
3067 | 70 | failstr = "crashed"; | 70 | break; |
3068 | 71 | break; | 71 | case ubuntu::app_launch::Registry::FailureType::START_FAILURE: |
3069 | 72 | case UBUNTU_APP_LAUNCH_APP_FAILED_START_FAILURE: | 72 | std::cout << " (start failure)"; |
3070 | 73 | failstr = "startup"; | 73 | break; |
3071 | 74 | break; | 74 | } |
3072 | 75 | } | 75 | std::cout << std::endl; |
3073 | 76 | 76 | }); | |
3074 | 77 | g_print("Fail %s (%s)\n", appid, failstr); | 77 | |
3075 | 78 | return; | 78 | std::signal(SIGTERM, [](int signal) -> void { retval.set_value(EXIT_SUCCESS); }); |
3076 | 79 | } | 79 | return retval.get_future().get(); |
2990 | 80 | |||
2991 | 81 | |||
2992 | 82 | int | ||
2993 | 83 | main (int argc, gchar * argv[]) | ||
2994 | 84 | { | ||
2995 | 85 | ubuntu_app_launch_observer_add_app_starting(starting, NULL); | ||
2996 | 86 | ubuntu_app_launch_observer_add_app_started(started, NULL); | ||
2997 | 87 | ubuntu_app_launch_observer_add_app_stop(stopped, NULL); | ||
2998 | 88 | ubuntu_app_launch_observer_add_app_focus(focus, NULL); | ||
2999 | 89 | ubuntu_app_launch_observer_add_app_resumed(resumed, NULL); | ||
3000 | 90 | ubuntu_app_launch_observer_add_app_paused(paused, NULL); | ||
3001 | 91 | ubuntu_app_launch_observer_add_app_failed(fail, NULL); | ||
3002 | 92 | |||
3003 | 93 | GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); | ||
3004 | 94 | g_main_loop_run(mainloop); | ||
3005 | 95 | |||
3006 | 96 | ubuntu_app_launch_observer_delete_app_starting(starting, NULL); | ||
3007 | 97 | ubuntu_app_launch_observer_delete_app_started(started, NULL); | ||
3008 | 98 | ubuntu_app_launch_observer_delete_app_stop(stopped, NULL); | ||
3009 | 99 | ubuntu_app_launch_observer_delete_app_focus(focus, NULL); | ||
3010 | 100 | ubuntu_app_launch_observer_delete_app_resumed(resumed, NULL); | ||
3011 | 101 | ubuntu_app_launch_observer_delete_app_paused(paused, NULL); | ||
3012 | 102 | ubuntu_app_launch_observer_delete_app_failed(fail, NULL); | ||
3013 | 103 | |||
3014 | 104 | g_main_loop_unref(mainloop); | ||
3015 | 105 | |||
3016 | 106 | return 0; | ||
3077 | 107 | } | 80 | } |
3078 | 108 | 81 | ||
3079 | === modified file 'tools/ubuntu-helper-list.cpp' | |||
3080 | --- tools/ubuntu-helper-list.cpp 2016-02-09 21:12:54 +0000 | |||
3081 | +++ tools/ubuntu-helper-list.cpp 2016-11-07 20:56:13 +0000 | |||
3082 | @@ -17,8 +17,8 @@ | |||
3083 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
3084 | 18 | */ | 18 | */ |
3085 | 19 | 19 | ||
3086 | 20 | #include "libubuntu-app-launch/registry.h" | ||
3087 | 20 | #include <iostream> | 21 | #include <iostream> |
3088 | 21 | #include "libubuntu-app-launch/registry.h" | ||
3089 | 22 | 22 | ||
3090 | 23 | int main(int argc, char* argv[]) | 23 | int main(int argc, char* argv[]) |
3091 | 24 | { | 24 | { |
3092 | 25 | 25 | ||
3093 | === modified file 'tools/ubuntu-helper-start.cpp' | |||
3094 | --- tools/ubuntu-helper-start.cpp 2016-05-03 01:46:27 +0000 | |||
3095 | +++ tools/ubuntu-helper-start.cpp 2016-11-07 20:56:13 +0000 | |||
3096 | @@ -17,9 +17,9 @@ | |||
3097 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
3098 | 18 | */ | 18 | */ |
3099 | 19 | 19 | ||
3100 | 20 | #include <iostream> | ||
3101 | 21 | #include "libubuntu-app-launch/helper.h" | 20 | #include "libubuntu-app-launch/helper.h" |
3102 | 22 | #include "libubuntu-app-launch/registry.h" | 21 | #include "libubuntu-app-launch/registry.h" |
3103 | 22 | #include <iostream> | ||
3104 | 23 | 23 | ||
3105 | 24 | int main(int argc, char* argv[]) | 24 | int main(int argc, char* argv[]) |
3106 | 25 | { | 25 | { |
3107 | @@ -31,20 +31,25 @@ | |||
3108 | 31 | 31 | ||
3109 | 32 | auto type = ubuntu::app_launch::Helper::Type::from_raw(argv[1]); | 32 | auto type = ubuntu::app_launch::Helper::Type::from_raw(argv[1]); |
3110 | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[2]); | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[2]); |
3112 | 34 | if (appid.empty()) { | 34 | if (appid.empty()) |
3113 | 35 | { | ||
3114 | 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; |
3115 | 36 | return 1; | 37 | return 1; |
3116 | 37 | } | 38 | } |
3117 | 38 | 39 | ||
3118 | 39 | auto registry = std::make_shared<ubuntu::app_launch::Registry>(); | 40 | auto registry = std::make_shared<ubuntu::app_launch::Registry>(); |
3119 | 40 | 41 | ||
3121 | 41 | try { | 42 | try |
3122 | 43 | { | ||
3123 | 42 | auto helper = ubuntu::app_launch::Helper::create(type, appid, registry); | 44 | auto helper = ubuntu::app_launch::Helper::create(type, appid, registry); |
3124 | 43 | 45 | ||
3125 | 44 | helper->launch(); | 46 | helper->launch(); |
3126 | 45 | return 0; | 47 | return 0; |
3129 | 46 | } catch (std::runtime_error &e) { | 48 | } |
3130 | 47 | std::cerr << "Unable to find helper for '" << std::string(appid) << "' type '" << type.value() << "': " << e.what() << std::endl; | 49 | catch (std::runtime_error& e) |
3131 | 50 | { | ||
3132 | 51 | std::cerr << "Unable to find helper for '" << std::string(appid) << "' type '" << type.value() | ||
3133 | 52 | << "': " << e.what() << std::endl; | ||
3134 | 48 | return 1; | 53 | return 1; |
3135 | 49 | } | 54 | } |
3136 | 50 | } | 55 | } |
3137 | 51 | 56 | ||
3138 | === modified file 'tools/ubuntu-helper-stop.cpp' | |||
3139 | --- tools/ubuntu-helper-stop.cpp 2016-05-03 01:46:27 +0000 | |||
3140 | +++ tools/ubuntu-helper-stop.cpp 2016-11-07 20:56:13 +0000 | |||
3141 | @@ -17,9 +17,9 @@ | |||
3142 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
3143 | 18 | */ | 18 | */ |
3144 | 19 | 19 | ||
3145 | 20 | #include <iostream> | ||
3146 | 21 | #include "libubuntu-app-launch/helper.h" | 20 | #include "libubuntu-app-launch/helper.h" |
3147 | 22 | #include "libubuntu-app-launch/registry.h" | 21 | #include "libubuntu-app-launch/registry.h" |
3148 | 22 | #include <iostream> | ||
3149 | 23 | 23 | ||
3150 | 24 | int main(int argc, char* argv[]) | 24 | int main(int argc, char* argv[]) |
3151 | 25 | { | 25 | { |
3152 | @@ -31,14 +31,16 @@ | |||
3153 | 31 | 31 | ||
3154 | 32 | auto type = ubuntu::app_launch::Helper::Type::from_raw(argv[1]); | 32 | auto type = ubuntu::app_launch::Helper::Type::from_raw(argv[1]); |
3155 | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[2]); | 33 | auto appid = ubuntu::app_launch::AppID::find(argv[2]); |
3157 | 34 | if (appid.empty()) { | 34 | if (appid.empty()) |
3158 | 35 | { | ||
3159 | 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; |
3160 | 36 | return 1; | 37 | return 1; |
3161 | 37 | } | 38 | } |
3162 | 38 | 39 | ||
3163 | 39 | auto registry = std::make_shared<ubuntu::app_launch::Registry>(); | 40 | auto registry = std::make_shared<ubuntu::app_launch::Registry>(); |
3164 | 40 | 41 | ||
3166 | 41 | try { | 42 | try |
3167 | 43 | { | ||
3168 | 42 | auto helper = ubuntu::app_launch::Helper::create(type, appid, registry); | 44 | auto helper = ubuntu::app_launch::Helper::create(type, appid, registry); |
3169 | 43 | 45 | ||
3170 | 44 | for (auto instance : helper->instances()) | 46 | for (auto instance : helper->instances()) |
3171 | @@ -47,8 +49,11 @@ | |||
3172 | 47 | } | 49 | } |
3173 | 48 | 50 | ||
3174 | 49 | return 0; | 51 | return 0; |
3177 | 50 | } catch (std::runtime_error &e) { | 52 | } |
3178 | 51 | std::cerr << "Unable to find helper for '" << std::string(appid) << "' type '" << type.value() << "': " << e.what() << std::endl; | 53 | catch (std::runtime_error& e) |
3179 | 54 | { | ||
3180 | 55 | std::cerr << "Unable to find helper for '" << std::string(appid) << "' type '" << type.value() | ||
3181 | 56 | << "': " << e.what() << std::endl; | ||
3182 | 52 | return 1; | 57 | return 1; |
3183 | 53 | } | 58 | } |
3184 | 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://