~mir-team/unity-mir/devel-mir-next

« back to all changes in this revision

Viewing changes to src/modules/Unity/Application/upstart/applicationcontroller.cpp

  • Committer: CI bot
  • Author(s): Gerry Boland
  • Date: 2014-05-16 12:20:55 UTC
  • mfrom: (219.1.16 shortAppIds)
  • Revision ID: ps-jenkins@lists.canonical.com-20140516122055-e5jw3w0k5obulsdr
Add support for short appIds

Shells should use only short AppIds (i.e. appId without the version string). In order to support this, needed to
- slightly decouple appId from the desktop file path, now need to ask the ApplicationController implementation for the path to the desktop file
- DesktopFileReader now just a dumb file reader
- in the upstart ApplicationController interface & implementation, convert any long appIds to short appIds
- in ApplicationManager, to ease transition, have startApplication support both long & short appIds. But otherwise it uses short appIds only. Fixes: 1239750

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
// unity-mir
21
21
#include <logging.h>
22
22
 
 
23
// Qt
 
24
#include <QStandardPaths>
 
25
 
23
26
// upstart
24
27
extern "C" {
25
28
    #include "upstart-app-launch.h"
40
43
    upstart_app_launch_app_failed_observer_t failureCallback = nullptr;
41
44
};
42
45
 
 
46
namespace {
 
47
/**
 
48
 * @brief toShortAppIdIfPossible
 
49
 * @param appId - any string that you think is an appId
 
50
 * @return if a valid appId was input, a shortened appId is returned, else returns the input string unaltered
 
51
 */
 
52
QString toShortAppIdIfPossible(const QString &appId) {
 
53
    gchar *package, *application;
 
54
    if (upstart_app_launch_app_id_parse(appId.toLatin1().constData(), &package, &application, nullptr)) {
 
55
        // is long appId, so assemble its short appId
 
56
        QString shortAppId = QString("%1_%2").arg(package).arg(application);
 
57
        g_free(package);
 
58
        g_free(application);
 
59
        return shortAppId;
 
60
    } else {
 
61
        return appId;
 
62
    }
 
63
}
 
64
 
 
65
/**
 
66
 * @brief toLongAppIdIfPossible
 
67
 * @param shortAppId - any string that you think is a short appId
 
68
 * @return if valid short appId was input, the corresponding long appId is returned. If a long appId was
 
69
 * entered, it is returned unchanged. Anything else is also returned unchanged.
 
70
 */
 
71
QString toLongAppIdIfPossible(const QString &shortAppId) {
 
72
    if (upstart_app_launch_app_id_parse(shortAppId.toLatin1().constData(), nullptr, nullptr, nullptr)) {
 
73
        // then we got a long appId after all, just return it
 
74
        return shortAppId;
 
75
    } else {
 
76
        // try to parse the string in the form "$package_$application"
 
77
        QRegExp shortAppIdMask("[a-z0-9][a-z0-9+.-]+_[a-zA-Z0-9+.-]+");
 
78
        if (!shortAppIdMask.exactMatch(shortAppId)) {
 
79
            // input string not a short appId, so just return it unchanged
 
80
            return shortAppId;
 
81
        }
 
82
 
 
83
        // ask upstart for the long appId corresponding to this short appId
 
84
        QStringList parts = shortAppId.split("_");
 
85
        gchar *longAppId;
 
86
        longAppId = upstart_app_launch_triplet_to_app_id(parts.first().toLatin1().constData(),
 
87
                                                         parts.last().toLatin1().constData(),
 
88
                                                         nullptr);
 
89
        if (longAppId == nullptr) {
 
90
            // was unable to construct a long appId from the short appId, return input unchanged
 
91
            return shortAppId;
 
92
        } else {
 
93
            QString appId(longAppId);
 
94
            g_free(longAppId);
 
95
            return appId;
 
96
        }
 
97
    }
 
98
}
 
99
 
 
100
} // namespace
 
101
 
43
102
ApplicationController::ApplicationController()
44
103
    : unitymir::ApplicationController(),
45
104
      impl(new Private())
46
105
{
47
106
    impl->preStartCallback = [](const gchar * appId, gpointer userData) {
48
107
        auto thiz = static_cast<ApplicationController*>(userData);
49
 
        Q_EMIT(thiz->applicationAboutToBeStarted(appId));
 
108
        Q_EMIT(thiz->applicationAboutToBeStarted(toShortAppIdIfPossible(appId)));
50
109
    };
51
110
 
52
111
    impl->startedCallback = [](const gchar * appId, gpointer userData) {
53
112
        auto thiz = static_cast<ApplicationController*>(userData);
54
 
        Q_EMIT(thiz->applicationStarted(appId));
 
113
        Q_EMIT(thiz->applicationStarted(toShortAppIdIfPossible(appId)));
55
114
    };
56
115
 
57
116
    impl->stopCallback = [](const gchar * appId, gpointer userData) {
58
117
        auto thiz = static_cast<ApplicationController*>(userData);
59
 
        Q_EMIT(thiz->applicationStopped(appId));
 
118
        Q_EMIT(thiz->applicationStopped(toShortAppIdIfPossible(appId)));
60
119
    };
61
120
 
62
121
    impl->focusCallback = [](const gchar * appId, gpointer userData) {
63
122
        auto thiz = static_cast<ApplicationController*>(userData);
64
 
        Q_EMIT(thiz->applicationFocusRequest(appId));
 
123
        Q_EMIT(thiz->applicationFocusRequest(toShortAppIdIfPossible(appId)));
65
124
    };
66
125
 
67
126
    impl->resumeCallback = [](const gchar * appId, gpointer userData) {
68
127
        auto thiz = static_cast<ApplicationController*>(userData);
69
 
        Q_EMIT(thiz->applicationResumeRequest(appId));
 
128
        Q_EMIT(thiz->applicationResumeRequest(toShortAppIdIfPossible(appId)));
70
129
    };
71
130
 
72
131
    impl->failureCallback = [](const gchar * appId, upstart_app_launch_app_failed_t failureType, gpointer userData) {
78
137
        }
79
138
 
80
139
        auto thiz = static_cast<ApplicationController*>(userData);
81
 
        Q_EMIT(thiz->applicationError(appId, error));
 
140
        Q_EMIT(thiz->applicationError(toShortAppIdIfPossible(appId), error));
82
141
    };
83
142
 
84
143
    upstart_app_launch_observer_add_app_starting(impl->preStartCallback, this);
101
160
 
102
161
pid_t ApplicationController::primaryPidForAppId(const QString& appId)
103
162
{
104
 
    GPid pid = upstart_app_launch_get_primary_pid(appId.toLatin1().constData());
 
163
    GPid pid = upstart_app_launch_get_primary_pid(toLongAppIdIfPossible(appId).toLatin1().constData());
105
164
    DLOG_IF(!pid, "ApplicationController::stopApplication appId='%s' FAILED", qPrintable(appId));
106
165
 
107
166
    return pid;
109
168
 
110
169
bool ApplicationController::appIdHasProcessId(pid_t pid, const QString& appId)
111
170
{
112
 
    return upstart_app_launch_pid_in_app_id(pid, appId.toLatin1().constData());
 
171
    return upstart_app_launch_pid_in_app_id(pid, toLongAppIdIfPossible(appId).toLatin1().constData());
113
172
}
114
173
 
115
174
bool ApplicationController::stopApplicationWithAppId(const QString& appId)
116
175
{
117
 
    auto result = upstart_app_launch_stop_application(appId.toLatin1().constData());
 
176
    auto result = upstart_app_launch_stop_application(toLongAppIdIfPossible(appId).toLatin1().constData());
118
177
    DLOG_IF(!result, "ApplicationController::stopApplicationWithAppId appId='%s' FAILED", qPrintable(appId));
119
178
    return result;
120
179
}
130
189
    }
131
190
 
132
191
    auto result = upstart_app_launch_start_application(
133
 
                appId.toLatin1().constData(),
 
192
                toLongAppIdIfPossible(appId).toLatin1().constData(),
134
193
                static_cast<const gchar * const *>(upstartArgs));
135
194
 
136
195
    g_strfreev(upstartArgs);
139
198
    return result;
140
199
}
141
200
 
 
201
QFileInfo ApplicationController::findDesktopFileForAppId(const QString &appId) const
 
202
{
 
203
    DLOG("ApplicationController::desktopFilePathForAppId (appId='%s')", qPrintable(appId));
 
204
 
 
205
    // Search for the correct desktop file using a simple heuristic
 
206
    int dashPos = -1;
 
207
    QString helper = toLongAppIdIfPossible(appId);
 
208
    QString desktopFile;
 
209
 
 
210
    do {
 
211
        if (dashPos != -1) {
 
212
            helper = helper.replace(dashPos, 1, '/');
 
213
        }
 
214
 
 
215
        desktopFile = QStandardPaths::locate(QStandardPaths::ApplicationsLocation, QString("%1.desktop").arg(helper));
 
216
        if (!desktopFile.isEmpty()) return desktopFile;
 
217
 
 
218
        dashPos = helper.indexOf("-");
 
219
    } while (dashPos != -1);
 
220
 
 
221
    return QFileInfo();
 
222
}
 
223
 
142
224
} // namespace upstart
143
225
} // namespace unitymir