~alan-griffiths/miral/fix-1645284

« back to all changes in this revision

Viewing changes to miral-qt/src/modules/Unity/Application/upstart/taskcontroller.cpp

  • Committer: Alan Griffiths
  • Date: 2016-11-07 17:59:19 UTC
  • mfrom: (436.1.1 miral2)
  • Revision ID: alan@octopull.co.uk-20161107175919-stbb64i7j1htgog2
[miral-qt] delete all as qtmir work on MirAL has shifted to lp:~unity-team/qtmir/miral-qt-integration and this is a needless distration

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2014-2016 Canonical, Ltd.
3
 
 *
4
 
 * This program is free software: you can redistribute it and/or modify it under
5
 
 * the terms of the GNU Lesser General Public License version 3, as published by
6
 
 * the Free Software Foundation.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful, but WITHOUT
9
 
 * ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
10
 
 * SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11
 
 * Lesser General Public License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU Lesser General Public License
14
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 
 *
16
 
 */
17
 
 
18
 
#include "applicationinfo.h"
19
 
#include "taskcontroller.h"
20
 
 
21
 
// qtmir
22
 
#include <logging.h>
23
 
 
24
 
// Qt
25
 
#include <QStandardPaths>
26
 
 
27
 
// upstart
28
 
extern "C" {
29
 
    #include "ubuntu-app-launch.h"
30
 
}
31
 
#include <ubuntu-app-launch/registry.h>
32
 
 
33
 
namespace ual = ubuntu::app_launch;
34
 
 
35
 
namespace qtmir
36
 
{
37
 
namespace upstart
38
 
{
39
 
 
40
 
struct TaskController::Private
41
 
{
42
 
    std::shared_ptr<ual::Registry> registry;
43
 
    UbuntuAppLaunchAppObserver preStartCallback = nullptr;
44
 
    UbuntuAppLaunchAppObserver startedCallback = nullptr;
45
 
    UbuntuAppLaunchAppObserver stopCallback = nullptr;
46
 
    UbuntuAppLaunchAppObserver focusCallback = nullptr;
47
 
    UbuntuAppLaunchAppObserver resumeCallback = nullptr;
48
 
    UbuntuAppLaunchAppPausedResumedObserver pausedCallback = nullptr;
49
 
    UbuntuAppLaunchAppFailedObserver failureCallback = nullptr;
50
 
};
51
 
 
52
 
namespace {
53
 
/**
54
 
 * @brief toShortAppIdIfPossible
55
 
 * @param appId - any string that you think is an appId
56
 
 * @return if a valid appId was input, a shortened appId is returned, else returns the input string unaltered
57
 
 */
58
 
QString toShortAppIdIfPossible(const QString &appId) {
59
 
    gchar *package, *application;
60
 
    if (ubuntu_app_launch_app_id_parse(appId.toLatin1().constData(), &package, &application, nullptr)) {
61
 
        // is long appId, so assemble its short appId
62
 
        QString shortAppId = QStringLiteral("%1_%2").arg(package, application);
63
 
        g_free(package);
64
 
        g_free(application);
65
 
        return shortAppId;
66
 
    } else {
67
 
        return appId;
68
 
    }
69
 
}
70
 
 
71
 
std::shared_ptr<ual::Application> createApp(const QString &inputAppId, std::shared_ptr<ual::Registry> registry)
72
 
{
73
 
    auto appId = ual::AppID::find(inputAppId.toStdString());
74
 
    if (appId.empty()) {
75
 
        qCDebug(QTMIR_APPLICATIONS) << "ApplicationController::createApp could not find appId" << inputAppId;
76
 
        return {};
77
 
    }
78
 
 
79
 
    try {
80
 
        return ual::Application::create(appId, registry);
81
 
    } catch (std::runtime_error e) {
82
 
        qCDebug(QTMIR_APPLICATIONS) << "ApplicationController::createApp - UAL failed to create app for appId"
83
 
                                    << inputAppId << ":" << e.what();
84
 
        return {};
85
 
    }
86
 
}
87
 
 
88
 
} // namespace
89
 
 
90
 
TaskController::TaskController()
91
 
    : qtmir::TaskController(),
92
 
      impl(new Private())
93
 
{
94
 
    impl->registry = std::make_shared<ual::Registry>();
95
 
 
96
 
    impl->preStartCallback = [](const gchar * appId, gpointer userData) {
97
 
        auto thiz = static_cast<TaskController*>(userData);
98
 
        Q_EMIT(thiz->processStarting(toShortAppIdIfPossible(appId)));
99
 
    };
100
 
 
101
 
    impl->startedCallback = [](const gchar * appId, gpointer userData) {
102
 
        auto thiz = static_cast<TaskController*>(userData);
103
 
        Q_EMIT(thiz->applicationStarted(toShortAppIdIfPossible(appId)));
104
 
    };
105
 
 
106
 
    impl->stopCallback = [](const gchar * appId, gpointer userData) {
107
 
        auto thiz = static_cast<TaskController*>(userData);
108
 
        Q_EMIT(thiz->processStopped(toShortAppIdIfPossible(appId)));
109
 
    };
110
 
 
111
 
    impl->focusCallback = [](const gchar * appId, gpointer userData) {
112
 
        auto thiz = static_cast<TaskController*>(userData);
113
 
        Q_EMIT(thiz->focusRequested(toShortAppIdIfPossible(appId)));
114
 
    };
115
 
 
116
 
    impl->resumeCallback = [](const gchar * appId, gpointer userData) {
117
 
        auto thiz = static_cast<TaskController*>(userData);
118
 
        Q_EMIT(thiz->resumeRequested(toShortAppIdIfPossible(appId)));
119
 
    };
120
 
 
121
 
    impl->pausedCallback = [](const gchar * appId, GPid *, gpointer userData) {
122
 
        auto thiz = static_cast<TaskController*>(userData);
123
 
        Q_EMIT(thiz->processSuspended(toShortAppIdIfPossible(appId)));
124
 
    };
125
 
 
126
 
    impl->failureCallback = [](const gchar * appId, UbuntuAppLaunchAppFailed failureType, gpointer userData) {
127
 
        TaskController::Error error;
128
 
        switch(failureType)
129
 
        {
130
 
        case UBUNTU_APP_LAUNCH_APP_FAILED_CRASH: error = TaskController::Error::APPLICATION_CRASHED;                    break;
131
 
        case UBUNTU_APP_LAUNCH_APP_FAILED_START_FAILURE: error = TaskController::Error::APPLICATION_FAILED_TO_START;    break;
132
 
        }
133
 
 
134
 
        auto thiz = static_cast<TaskController*>(userData);
135
 
        Q_EMIT(thiz->processFailed(toShortAppIdIfPossible(appId), error));
136
 
    };
137
 
 
138
 
    ubuntu_app_launch_observer_add_app_starting(impl->preStartCallback, this);
139
 
    ubuntu_app_launch_observer_add_app_started(impl->startedCallback, this);
140
 
    ubuntu_app_launch_observer_add_app_stop(impl->stopCallback, this);
141
 
    ubuntu_app_launch_observer_add_app_focus(impl->focusCallback, this);
142
 
    ubuntu_app_launch_observer_add_app_resume(impl->resumeCallback, this);
143
 
    ubuntu_app_launch_observer_add_app_paused(impl->pausedCallback, this);
144
 
    ubuntu_app_launch_observer_add_app_failed(impl->failureCallback, this);
145
 
}
146
 
 
147
 
TaskController::~TaskController()
148
 
{
149
 
    ubuntu_app_launch_observer_delete_app_starting(impl->preStartCallback, this);
150
 
    ubuntu_app_launch_observer_delete_app_started(impl->startedCallback, this);
151
 
    ubuntu_app_launch_observer_delete_app_stop(impl->stopCallback, this);
152
 
    ubuntu_app_launch_observer_delete_app_focus(impl->focusCallback, this);
153
 
    ubuntu_app_launch_observer_delete_app_resume(impl->resumeCallback, this);
154
 
    ubuntu_app_launch_observer_delete_app_paused(impl->pausedCallback, this);
155
 
    ubuntu_app_launch_observer_delete_app_failed(impl->failureCallback, this);
156
 
}
157
 
 
158
 
bool TaskController::appIdHasProcessId(const QString& appId, pid_t pid)
159
 
{
160
 
    auto app = createApp(appId, impl->registry);
161
 
    if (!app) {
162
 
        return false;
163
 
    }
164
 
 
165
 
    for (auto &instance: app->instances()) {
166
 
        if (instance->hasPid(pid)) {
167
 
            return true;
168
 
        }
169
 
    }
170
 
 
171
 
    return false;
172
 
}
173
 
 
174
 
bool TaskController::stop(const QString& appId)
175
 
{
176
 
    auto app = createApp(appId, impl->registry);
177
 
    if (!app) {
178
 
        return false;
179
 
    }
180
 
 
181
 
    for (auto &instance: app->instances()) {
182
 
        instance->stop();
183
 
    }
184
 
 
185
 
    return true;
186
 
}
187
 
 
188
 
bool TaskController::start(const QString& appId, const QStringList& arguments)
189
 
{
190
 
    auto app = createApp(appId, impl->registry);
191
 
    if (!app) {
192
 
        return false;
193
 
    }
194
 
 
195
 
    // Convert arguments QStringList into format suitable for ubuntu-app-launch
196
 
    std::vector<ual::Application::URL> urls;
197
 
    for (auto &arg: arguments) {
198
 
        urls.emplace_back(ual::Application::URL::from_raw(arg.toStdString()));
199
 
    }
200
 
 
201
 
    app->launch(urls);
202
 
 
203
 
    return true;
204
 
}
205
 
 
206
 
bool TaskController::suspend(const QString& appId)
207
 
{
208
 
    auto app = createApp(appId, impl->registry);
209
 
    if (!app) {
210
 
        return false;
211
 
    }
212
 
 
213
 
    for (auto &instance: app->instances()) {
214
 
        instance->pause();
215
 
    }
216
 
 
217
 
    return true;
218
 
}
219
 
 
220
 
bool TaskController::resume(const QString& appId)
221
 
{
222
 
    auto app = createApp(appId, impl->registry);
223
 
    if (!app) {
224
 
        return false;
225
 
    }
226
 
 
227
 
    for (auto &instance: app->instances()) {
228
 
        instance->resume();
229
 
    }
230
 
 
231
 
    return true;
232
 
}
233
 
 
234
 
QSharedPointer<qtmir::ApplicationInfo> TaskController::getInfoForApp(const QString &appId) const
235
 
{
236
 
    auto app = createApp(appId, impl->registry);
237
 
    if (!app || !app->info()) {
238
 
        return QSharedPointer<qtmir::ApplicationInfo>();
239
 
    }
240
 
 
241
 
    QString shortAppId = toShortAppIdIfPossible(QString::fromStdString(std::string(app->appId())));
242
 
    auto appInfo = new qtmir::upstart::ApplicationInfo(shortAppId, app->info());
243
 
    return QSharedPointer<qtmir::ApplicationInfo>(appInfo);
244
 
}
245
 
 
246
 
} // namespace upstart
247
 
} // namespace qtmir