40
46
Base::Base(const std::shared_ptr<Registry>& registry)
41
47
: registry_(registry)
42
, allJobs_{"application-click", "application-legacy", "application-snap"}
48
, allApplicationJobs_{"application-legacy", "application-snap"}
43
49
, dbus_(registry->impl->_dbus)
49
auto dohandle = [&](guint& handle) {
52
g_dbus_connection_signal_unsubscribe(dbus_.get(), handle);
57
dohandle(handle_managerSignalFocus);
58
dohandle(handle_managerSignalResume);
59
dohandle(handle_managerSignalStarting);
60
dohandle(handle_appPaused);
61
dohandle(handle_appResumed);
57
/** Should determine which jobs backend to use, but we only have
64
59
std::shared_ptr<Base> Base::determineFactory(std::shared_ptr<Registry> registry)
66
/* Checking to see if we have a user bus, that is only started
67
by systemd so we're in good shape if we have one. We're using
68
the path instead of the RUNTIME variable because we want to work
69
around the case of being relocated by the snappy environment */
70
if (g_file_test(SystemD::userBusPath().c_str(), G_FILE_TEST_EXISTS))
72
g_debug("Building a systemd jobs manager");
73
return std::make_shared<jobs::manager::SystemD>(registry);
77
g_debug("Building an Upstart jobs manager");
78
return std::make_shared<jobs::manager::Upstart>(registry);
82
const std::set<std::string>& Base::getAllJobs() const
61
g_debug("Building a systemd jobs manager");
62
return std::make_shared<jobs::manager::SystemD>(registry);
65
const std::list<std::string>& Base::getAllApplicationJobs() const
67
return allApplicationJobs_;
70
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& Base::appStarted()
72
std::call_once(flag_appStarted, [this]() {
73
jobStarted().connect([this](const std::string& job, const std::string& appid, const std::string& instanceid) {
74
if (std::find(allApplicationJobs_.begin(), allApplicationJobs_.end(), job) == allApplicationJobs_.end())
76
/* Not an application, different signal */
82
auto reg = registry_.lock();
84
auto appId = AppID::find(reg, appid);
85
auto app = Application::create(appId, reg);
86
auto inst = std::dynamic_pointer_cast<app_impls::Base>(app)->findInstance(instanceid);
88
sig_appStarted(app, inst);
90
catch (std::runtime_error& e)
92
g_warning("Error in appStarted signal from job: %s", e.what());
97
return sig_appStarted;
100
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&>& Base::appStopped()
102
std::call_once(flag_appStopped, [this]() {
103
jobStopped().connect([this](const std::string& job, const std::string& appid, const std::string& instanceid) {
104
if (std::find(allApplicationJobs_.begin(), allApplicationJobs_.end(), job) == allApplicationJobs_.end())
106
/* Not an application, different signal */
112
auto reg = registry_.lock();
114
auto appId = AppID::find(reg, appid);
115
auto app = Application::create(appId, reg);
116
auto inst = std::dynamic_pointer_cast<app_impls::Base>(app)->findInstance(instanceid);
118
sig_appStopped(app, inst);
120
catch (std::runtime_error& e)
122
g_warning("Error in appStopped signal from job: %s", e.what());
127
return sig_appStopped;
130
core::Signal<const std::shared_ptr<Application>&, const std::shared_ptr<Application::Instance>&, Registry::FailureType>&
133
std::call_once(flag_appFailed, [this]() {
134
jobFailed().connect([this](const std::string& job, const std::string& appid, const std::string& instanceid,
135
Registry::FailureType reason) {
136
if (std::find(allApplicationJobs_.begin(), allApplicationJobs_.end(), job) == allApplicationJobs_.end())
138
/* Not an application, different signal */
144
auto reg = registry_.lock();
146
auto appId = AppID::find(reg, appid);
147
auto app = Application::create(appId, reg);
148
auto inst = std::dynamic_pointer_cast<app_impls::Base>(app)->findInstance(instanceid);
150
sig_appFailed(app, inst, reason);
152
catch (std::runtime_error& e)
154
g_warning("Error in appFailed signal from job: %s", e.what());
159
return sig_appFailed;
87
162
/** Structure to track the data needed for upstart events. This cleans
103
178
const std::shared_ptr<Registry>& reg)
105
180
std::vector<pid_t> pids;
106
GVariant* vappid = g_variant_get_child_value(params.get(), 0);
107
GVariant* vinstid = g_variant_get_child_value(params.get(), 1);
108
GVariant* vpids = g_variant_get_child_value(params.get(), 2);
181
auto vappid = unique_glib(g_variant_get_child_value(params.get(), 0));
182
auto vinstid = unique_glib(g_variant_get_child_value(params.get(), 1));
183
auto vpids = unique_glib(g_variant_get_child_value(params.get(), 2));
110
185
GVariantIter thispid;
111
g_variant_iter_init(&thispid, vpids);
186
g_variant_iter_init(&thispid, vpids.get());
113
188
while (g_variant_iter_loop(&thispid, "t", &pid))
115
190
pids.emplace_back(pid);
118
auto cappid = g_variant_get_string(vappid, NULL);
119
auto cinstid = g_variant_get_string(vinstid, NULL);
193
auto cappid = g_variant_get_string(vappid.get(), NULL);
194
auto cinstid = g_variant_get_string(vinstid.get(), NULL);
121
196
auto appid = ubuntu::app_launch::AppID::find(reg, cappid);
122
197
auto app = Application::create(appid, reg);
144
215
reg->impl->thread.executeOnThread<bool>([this, reg]() {
145
216
upstartEventData* data = new upstartEventData{reg};
147
handle_appPaused = g_dbus_connection_signal_subscribe(
148
reg->impl->_dbus.get(), /* bus */
149
nullptr, /* sender */
150
"com.canonical.UbuntuAppLaunch", /* interface */
151
"ApplicationPaused", /* signal */
154
G_DBUS_SIGNAL_FLAGS_NONE,
155
[](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params,
156
gpointer user_data) -> void {
157
auto data = reinterpret_cast<upstartEventData*>(user_data);
158
auto reg = data->weakReg.lock();
162
g_warning("Registry object invalid!");
166
auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref);
167
auto manager = std::dynamic_pointer_cast<Base>(reg->impl->jobs);
168
manager->pauseEventEmitted(manager->sig_appPaused, sparams, reg);
170
data, /* user data */
171
[](gpointer user_data) {
172
auto data = reinterpret_cast<upstartEventData*>(user_data);
174
}); /* user data destroy */
218
handle_appPaused = managedDBusSignalConnection(
219
g_dbus_connection_signal_subscribe(reg->impl->_dbus.get(), /* bus */
220
nullptr, /* sender */
221
"com.canonical.UbuntuAppLaunch", /* interface */
222
"ApplicationPaused", /* signal */
225
G_DBUS_SIGNAL_FLAGS_NONE,
226
[](GDBusConnection*, const gchar*, const gchar*, const gchar*,
227
const gchar*, GVariant* params, gpointer user_data) -> void {
228
auto data = reinterpret_cast<upstartEventData*>(user_data);
229
auto reg = data->weakReg.lock();
233
g_warning("Registry object invalid!");
237
auto sparams = share_glib(g_variant_ref(params));
238
auto manager = std::dynamic_pointer_cast<Base>(reg->impl->jobs);
239
manager->pauseEventEmitted(manager->sig_appPaused, sparams, reg);
241
data, /* user data */
242
[](gpointer user_data) {
243
auto data = reinterpret_cast<upstartEventData*>(user_data);
245
}), /* user data destroy */
193
265
reg->impl->thread.executeOnThread<bool>([this, reg]() {
194
266
upstartEventData* data = new upstartEventData{reg};
196
handle_appResumed = g_dbus_connection_signal_subscribe(
197
reg->impl->_dbus.get(), /* bus */
198
nullptr, /* sender */
199
"com.canonical.UbuntuAppLaunch", /* interface */
200
"ApplicationResumed", /* signal */
203
G_DBUS_SIGNAL_FLAGS_NONE,
204
[](GDBusConnection*, const gchar*, const gchar*, const gchar*, const gchar*, GVariant* params,
205
gpointer user_data) -> void {
206
auto data = reinterpret_cast<upstartEventData*>(user_data);
207
auto reg = data->weakReg.lock();
211
g_warning("Registry object invalid!");
215
auto sparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref);
216
auto manager = std::dynamic_pointer_cast<Base>(reg->impl->jobs);
217
manager->pauseEventEmitted(manager->sig_appResumed, sparams, reg);
219
data, /* user data */
220
[](gpointer user_data) {
221
auto data = reinterpret_cast<upstartEventData*>(user_data);
223
}); /* user data destroy */
268
handle_appResumed = managedDBusSignalConnection(
269
g_dbus_connection_signal_subscribe(reg->impl->_dbus.get(), /* bus */
270
nullptr, /* sender */
271
"com.canonical.UbuntuAppLaunch", /* interface */
272
"ApplicationResumed", /* signal */
275
G_DBUS_SIGNAL_FLAGS_NONE,
276
[](GDBusConnection*, const gchar*, const gchar*, const gchar*,
277
const gchar*, GVariant* params, gpointer user_data) -> void {
278
auto data = reinterpret_cast<upstartEventData*>(user_data);
279
auto reg = data->weakReg.lock();
283
g_warning("Registry object invalid!");
287
auto sparams = share_glib(g_variant_ref(params));
288
auto manager = std::dynamic_pointer_cast<Base>(reg->impl->jobs);
289
manager->pauseEventEmitted(manager->sig_appResumed, sparams,
292
data, /* user data */
293
[](gpointer user_data) {
294
auto data = reinterpret_cast<upstartEventData*>(user_data);
296
}), /* user data destroy */
229
303
return sig_appResumed;
306
core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&>& Base::helperStarted(
311
return *sig_helpersStarted.at(type.value());
313
catch (std::out_of_range& e)
315
jobStarted().connect(
316
[this, type](const std::string& job, const std::string& appid, const std::string& instanceid) {
317
if (job != type.value())
324
auto reg = registry_.lock();
326
auto appId = ubuntu::app_launch::AppID::parse(appid);
327
auto helper = Helper::create(type, appId, reg);
328
auto inst = std::dynamic_pointer_cast<helper_impls::Base>(helper)->existingInstance(instanceid);
330
(*sig_helpersStarted.at(type.value()))(helper, inst);
334
g_warning("Unable to emit signal for helper type: %s", type.value().c_str());
338
sig_helpersStarted.emplace(
340
std::make_shared<core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&>>());
343
return *sig_helpersStarted.at(type.value());
346
core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&>& Base::helperStopped(
351
return *sig_helpersStopped.at(type.value());
353
catch (std::out_of_range& e)
355
jobStopped().connect(
356
[this, type](const std::string& job, const std::string& appid, const std::string& instanceid) {
357
if (job != type.value())
364
auto reg = registry_.lock();
366
auto appId = ubuntu::app_launch::AppID::parse(appid);
367
auto helper = Helper::create(type, appId, reg);
368
auto inst = std::dynamic_pointer_cast<helper_impls::Base>(helper)->existingInstance(instanceid);
370
(*sig_helpersStopped.at(type.value()))(helper, inst);
374
g_warning("Unable to emit signal for helper type: %s", type.value().c_str());
378
sig_helpersStopped.emplace(
380
std::make_shared<core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&>>());
383
return *sig_helpersStopped.at(type.value());
386
core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&, Registry::FailureType>&
387
Base::helperFailed(Helper::Type type)
391
return *sig_helpersFailed.at(type.value());
393
catch (std::out_of_range& e)
395
jobFailed().connect([this, type](const std::string& job, const std::string& appid,
396
const std::string& instanceid, Registry::FailureType reason) {
397
if (job != type.value())
404
auto reg = registry_.lock();
406
auto appId = ubuntu::app_launch::AppID::parse(appid);
407
auto helper = Helper::create(type, appId, reg);
408
auto inst = std::dynamic_pointer_cast<helper_impls::Base>(helper)->existingInstance(instanceid);
410
(*sig_helpersFailed.at(type.value()))(helper, inst, reason);
414
g_warning("Unable to emit signal for helper type: %s", type.value().c_str());
418
sig_helpersFailed.emplace(
420
std::make_shared<core::Signal<const std::shared_ptr<Helper>&, const std::shared_ptr<Helper::Instance>&,
421
Registry::FailureType>>());
424
return *sig_helpersFailed.at(type.value());
232
427
/** Take the GVariant of parameters and turn them into an application and
233
428
and instance. Easier to read in the smaller function */
234
429
std::tuple<std::shared_ptr<Application>, std::shared_ptr<Application::Instance>> Base::managerParams(
308
auto vparams = std::shared_ptr<GVariant>(g_variant_ref(params), g_variant_unref);
309
auto conn = std::shared_ptr<GDBusConnection>(reinterpret_cast<GDBusConnection*>(g_object_ref(cconn)),
310
[](GDBusConnection* con) { g_clear_object(&con); });
311
std::string sender = csender;
312
std::shared_ptr<Application> app;
313
std::shared_ptr<Application::Instance> instance;
315
std::tie(app, instance) = managerParams(vparams, reg);
317
data->func(reg, app, instance, conn, sender, vparams);
505
auto vparams = share_glib(g_variant_ref(params));
506
auto conn = share_gobject(G_DBUS_CONNECTION(g_object_ref(cconn)));
507
std::string sender = csender;
508
std::shared_ptr<Application> app;
509
std::shared_ptr<Application::Instance> instance;
511
std::tie(app, instance) = managerParams(vparams, reg);
513
data->func(reg, app, instance, conn, sender, vparams);
515
catch (std::runtime_error& e)
517
g_warning("Unable to call signal handler for manager signal: %s", e.what());
320
521
[](gpointer user_data) {
350
551
if (!reg->impl->thread.executeOnThread<bool>([this, reg]() {
351
handle_managerSignalFocus = managerSignalHelper(
352
reg, "UnityFocusRequest",
353
[](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app,
354
const std::shared_ptr<Application::Instance>& instance,
355
const std::shared_ptr<GDBusConnection>& conn, const std::string& sender,
356
const std::shared_ptr<GVariant>& params) {
357
/* Nothing to do today */
358
std::dynamic_pointer_cast<Base>(reg->impl->jobs)
359
->manager_->focusRequest(app, instance, [](bool response) {
360
/* NOTE: We have no clue what thread this is gonna be
361
executed on, but since we're just talking to the GDBus
362
thread it isn't an issue today. Be careful in changing
366
handle_managerSignalStarting = managerSignalHelper(
367
reg, "UnityStartingBroadcast",
368
[](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app,
369
const std::shared_ptr<Application::Instance>& instance,
370
const std::shared_ptr<GDBusConnection>& conn, const std::string& sender,
371
const std::shared_ptr<GVariant>& params) {
552
handle_managerSignalFocus = managedDBusSignalConnection(
554
reg, "UnityFocusRequest",
555
[](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app,
556
const std::shared_ptr<Application::Instance>& instance,
557
const std::shared_ptr<GDBusConnection>& conn, const std::string& sender,
558
const std::shared_ptr<GVariant>& params) {
559
/* Nothing to do today */
560
std::dynamic_pointer_cast<Base>(reg->impl->jobs)
561
->manager_->focusRequest(app, instance, [](bool response) {
562
/* NOTE: We have no clue what thread this is gonna be
563
executed on, but since we're just talking to the GDBus
564
thread it isn't an issue today. Be careful in changing
569
handle_managerSignalStarting = managedDBusSignalConnection(
571
reg, "UnityStartingBroadcast",
572
[](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app,
573
const std::shared_ptr<Application::Instance>& instance,
574
const std::shared_ptr<GDBusConnection>& conn, const std::string& sender,
575
const std::shared_ptr<GVariant>& params) {
373
std::dynamic_pointer_cast<Base>(reg->impl->jobs)
374
->manager_->startingRequest(app, instance, [conn, sender, params](bool response) {
375
/* NOTE: We have no clue what thread this is gonna be
376
executed on, but since we're just talking to the GDBus
377
thread it isn't an issue today. Be careful in changing
381
g_dbus_connection_emit_signal(conn.get(), sender.c_str(), /* destination */
383
"com.canonical.UbuntuAppLaunch", /* interface */
384
"UnityStartingSignal", /* signal */
385
params.get(), /* params, the same */
386
nullptr); /* error */
390
handle_managerSignalResume = managerSignalHelper(
391
reg, "UnityResumeRequest",
392
[](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app,
393
const std::shared_ptr<Application::Instance>& instance,
394
const std::shared_ptr<GDBusConnection>& conn, const std::string& sender,
395
const std::shared_ptr<GVariant>& params) {
396
std::dynamic_pointer_cast<Base>(reg->impl->jobs)
397
->manager_->resumeRequest(app, instance, [conn, sender, params](bool response) {
398
/* NOTE: We have no clue what thread this is gonna be
399
executed on, but since we're just talking to the GDBus
400
thread it isn't an issue today. Be careful in changing
404
g_dbus_connection_emit_signal(conn.get(), sender.c_str(), /* destination */
406
"com.canonical.UbuntuAppLaunch", /* interface */
407
"UnityResumeResponse", /* signal */
408
params.get(), /* params, the same */
409
nullptr); /* error */
577
std::dynamic_pointer_cast<Base>(reg->impl->jobs)
578
->manager_->startingRequest(app, instance, [conn, sender, params](bool response) {
579
/* NOTE: We have no clue what thread this is gonna be
580
executed on, but since we're just talking to the GDBus
581
thread it isn't an issue today. Be careful in changing
585
g_dbus_connection_emit_signal(conn.get(), sender.c_str(), /* destination */
587
"com.canonical.UbuntuAppLaunch", /* interface */
588
"UnityStartingSignal", /* signal */
589
params.get(), /* params, the same */
590
nullptr); /* error */
595
handle_managerSignalResume = managedDBusSignalConnection(
597
reg, "UnityResumeRequest",
598
[](const std::shared_ptr<Registry>& reg, const std::shared_ptr<Application>& app,
599
const std::shared_ptr<Application::Instance>& instance,
600
const std::shared_ptr<GDBusConnection>& conn, const std::string& sender,
601
const std::shared_ptr<GVariant>& params) {
602
std::dynamic_pointer_cast<Base>(reg->impl->jobs)
603
->manager_->resumeRequest(app, instance, [conn, sender, params](bool response) {
604
/* NOTE: We have no clue what thread this is gonna be
605
executed on, but since we're just talking to the GDBus
606
thread it isn't an issue today. Be careful in changing
610
g_dbus_connection_emit_signal(conn.get(), sender.c_str(), /* destination */
612
"com.canonical.UbuntuAppLaunch", /* interface */
613
"UnityResumeResponse", /* signal */
614
params.get(), /* params, the same */
615
nullptr); /* error */
426
633
manager_.reset();
636
/** Get application objects for all of the applications based
637
on the appids associated with the application jobs */
638
std::list<std::shared_ptr<Application>> Base::runningApps()
640
auto registry = registry_.lock();
644
g_warning("Unable to list apps without a registry");
648
auto appids = runningAppIds(allApplicationJobs_);
650
std::list<std::shared_ptr<Application>> apps;
651
for (const auto& appid : appids)
653
auto id = AppID::find(registry, appid);
656
g_debug("Unable to handle AppID: %s", appid.c_str());
662
apps.emplace_back(Application::create(id, registry));
664
catch (std::runtime_error& e)
666
g_debug("Error adding appid '%s' to running apps list: %s", appid.c_str(), e.what());
673
/** Get application objects for all of the applications based
674
on the appids associated with the application jobs */
675
std::list<std::shared_ptr<Helper>> Base::runningHelpers(const Helper::Type& type)
677
auto registry = registry_.lock();
681
g_warning("Unable to list helpers without a registry");
685
auto appids = runningAppIds({type.value()});
687
std::list<std::shared_ptr<Helper>> helpers;
688
for (const auto& appid : appids)
690
auto id = AppID::parse(appid);
693
g_debug("Unable to handle AppID: %s", appid.c_str());
697
helpers.emplace_back(Helper::create(type, id, registry));
429
703
} // namespace manager
431
705
namespace instance