~mardy/ubuntu-system-settings-online-accounts/click-plugins-old

« back to all changes in this revision

Viewing changes to online-accounts-service/ui-proxy.cpp

  • Committer: Alberto Mardegan
  • Date: 2014-11-18 11:56:01 UTC
  • Revision ID: alberto.mardegan@canonical.com-20141118115601-0sclep3ly8pvlnjz
WIP

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
#include "request.h"
25
25
#include "ui-proxy.h"
26
26
 
 
27
#include <Accounts/Manager>
 
28
#include <Accounts/Provider>
27
29
#include <QDir>
 
30
#include <QDomDocument>
 
31
#include <QDomElement>
28
32
#include <QFileInfo>
29
33
#include <QLocalServer>
30
34
#include <QLocalSocket>
31
 
#include <QProcess>
32
35
#include <QProcessEnvironment>
33
36
#include <QStandardPaths>
34
37
#include <SignOn/uisessiondata_priv.h>
 
38
#include <ubuntu-app-launch.h>
35
39
 
36
40
using namespace OnlineAccountsUi;
37
41
 
48
52
    inline UiProxyPrivate(pid_t clientPid, UiProxy *pluginProxy);
49
53
    inline ~UiProxyPrivate();
50
54
 
 
55
    void setStatus(UiProxy::Status status);
51
56
    bool setupSocket();
52
57
    bool init();
53
58
    void sendOperation(const QVariantMap &data);
54
59
    void sendRequest(int requestId, Request *request);
55
 
    void setupPromptSession();
 
60
    QString setupPromptSession();
 
61
    QString findAppArmorProfile();
 
62
    void startProcess();
56
63
 
57
64
private Q_SLOTS:
58
65
    void onNewConnection();
60
67
    void onRequestCompleted();
61
68
 
62
69
private:
63
 
    QProcess m_process;
 
70
    UiProxy::Status m_status;
64
71
    QLocalServer m_server;
65
72
    QLocalSocket *m_socket;
66
73
    OnlineAccountsUi::Ipc m_ipc;
69
76
    QStringList m_handlers;
70
77
    pid_t m_clientPid;
71
78
    PromptSession *m_promptSession;
 
79
    QList<QByteArray> m_arguments;
72
80
    mutable UiProxy *q_ptr;
73
81
};
74
82
 
76
84
 
77
85
UiProxyPrivate::UiProxyPrivate(pid_t clientPid, UiProxy *uiProxy):
78
86
    QObject(uiProxy),
 
87
    m_status(UiProxy::Null),
79
88
    m_socket(0),
80
89
    m_nextRequestId(0),
81
90
    m_clientPid(clientPid),
86
95
                     this, SLOT(onNewConnection()));
87
96
    QObject::connect(&m_ipc, SIGNAL(dataReady(QByteArray &)),
88
97
                     this, SLOT(onDataReady(QByteArray &)));
89
 
    m_process.setProcessChannelMode(QProcess::ForwardedChannels);
90
98
}
91
99
 
92
100
UiProxyPrivate::~UiProxyPrivate()
105
113
    m_server.close();
106
114
}
107
115
 
 
116
void UiProxyPrivate::setStatus(UiProxy::Status status)
 
117
{
 
118
    Q_Q(UiProxy);
 
119
    if (m_status == status) return;
 
120
    m_status = status;
 
121
    Q_EMIT q->statusChanged();
 
122
}
 
123
 
108
124
void UiProxyPrivate::sendOperation(const QVariantMap &data)
109
125
{
110
126
    QByteArray ba;
132
148
    m_ipc.setChannels(socket, socket);
133
149
    m_server.close(); // stop listening
134
150
 
 
151
    setStatus(UiProxy::Ready);
 
152
 
135
153
    /* Execute any pending requests */
136
154
    QMapIterator<int, Request*> it(m_requests);
137
155
    while (it.hasNext()) {
185
203
    return m_server.listen(socketDir.filePath(uniqueName));
186
204
}
187
205
 
188
 
void UiProxyPrivate::setupPromptSession()
 
206
QString UiProxyPrivate::setupPromptSession()
189
207
{
190
208
    Q_Q(UiProxy);
191
209
 
192
210
    QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
193
 
    if (!env.value("QT_QPA_PLATFORM").startsWith("ubuntu")) return;
 
211
    if (!env.value("QT_QPA_PLATFORM").startsWith("ubuntu")) return QString();
194
212
 
195
213
    PromptSession *session =
196
214
        MirHelper::instance()->createPromptSession(m_clientPid);
197
 
    if (!session) return;
 
215
    if (!session) return QString();
198
216
 
199
217
    QString mirSocket = session->requestSocket();
200
218
    if (mirSocket.isEmpty()) {
201
219
        delete session;
202
 
        return;
 
220
        return mirSocket;
203
221
    }
204
222
 
205
223
    m_promptSession = session;
206
224
    QObject::connect(m_promptSession, SIGNAL(finished()),
207
225
                     q, SIGNAL(finished()));
208
226
 
209
 
    env.insert("MIR_SOCKET", mirSocket);
210
 
    m_process.setProcessEnvironment(env);
 
227
    return mirSocket;
211
228
}
212
229
 
213
230
bool UiProxyPrivate::init()
214
231
{
215
232
    if (Q_UNLIKELY(!setupSocket())) return false;
216
233
 
217
 
    QString processName;
218
 
    QStringList arguments;
219
 
    QString wrapper = QString::fromUtf8(qgetenv("OAU_WRAPPER"));
220
 
    QString accountsUi = QStringLiteral(INSTALL_BIN_DIR "/online-accounts-ui");
221
 
    if (wrapper.isEmpty()) {
222
 
        processName = accountsUi;
223
 
    } else {
224
 
        processName = wrapper;
225
 
        arguments.append(accountsUi);
226
 
    }
227
 
    if (!m_promptSession) {
228
 
        /* the first argument is required to be the desktop file */
229
 
        arguments.append("--desktop_file_hint=/usr/share/applications/online-accounts-ui.desktop");
230
 
    }
231
 
    arguments.append("--socket");
232
 
    arguments.append(m_server.fullServerName());
 
234
    m_arguments.clear();
 
235
    m_arguments.append(m_server.fullServerName().toUtf8());
233
236
 
 
237
    QByteArray mirSocket;
234
238
    if (m_clientPid) {
235
 
        setupPromptSession();
236
 
    }
237
 
 
238
 
    m_process.start(processName, arguments);
239
 
    return m_process.waitForStarted();
 
239
        mirSocket = setupPromptSession().toUtf8();
 
240
    }
 
241
    if (mirSocket.isEmpty()) {
 
242
        mirSocket = "invalid://url";
 
243
    }
 
244
    m_arguments.append(mirSocket);
 
245
    return true;
 
246
}
 
247
 
 
248
QString UiProxyPrivate::findAppArmorProfile()
 
249
{
 
250
    QString providerId;
 
251
    /* Look through the requests, and look for the first one which has a
 
252
     * provider set. We'll use that provider's AppArmor id for confinement. */
 
253
    Q_FOREACH(Request *request, m_requests) {
 
254
        providerId = request->providerId();
 
255
        if (!providerId.isEmpty())
 
256
            break;
 
257
    }
 
258
 
 
259
    if (Q_UNLIKELY(providerId.isEmpty())) return QString();
 
260
 
 
261
    /* Load the provider XML file */
 
262
    Accounts::Manager manager;
 
263
    Accounts::Provider provider = manager.provider(providerId);
 
264
    if (Q_UNLIKELY(!provider.isValid())) {
 
265
        qWarning() << "Provider not found:" << providerId;
 
266
        return QString();
 
267
    }
 
268
 
 
269
    const QDomDocument doc = provider.domDocument();
 
270
    QDomElement root = doc.documentElement();
 
271
    return root.firstChildElement("profile").text();
 
272
}
 
273
 
 
274
void UiProxyPrivate::startProcess()
 
275
{
 
276
    QVector<const gchar*> uris;
 
277
    Q_FOREACH(const QByteArray &arg, m_arguments) {
 
278
        uris.append(arg.constData());
 
279
    }
 
280
    uris.append(NULL);
 
281
 
 
282
    QString profile = findAppArmorProfile();
 
283
    if (profile.isEmpty()) {
 
284
        profile = "unconfined";
 
285
    }
 
286
 
 
287
    gchar *instanceId =
 
288
        ubuntu_app_launch_start_multiple_helper("online-accounts-ui",
 
289
                                                profile.toUtf8().constData(),
 
290
                                                uris.constData());
 
291
    if (Q_UNLIKELY(instanceId == NULL)) {
 
292
        qWarning() << "Couldn't start account plugin process";
 
293
        setStatus(UiProxy::Error);
 
294
        return;
 
295
    }
 
296
 
 
297
    setStatus(UiProxy::Loading);
240
298
}
241
299
 
242
300
void UiProxyPrivate::sendRequest(int requestId, Request *request)
275
333
{
276
334
}
277
335
 
 
336
UiProxy::Status UiProxy::status() const
 
337
{
 
338
    Q_D(const UiProxy);
 
339
    return d->m_status;
 
340
}
 
341
 
278
342
bool UiProxy::init()
279
343
{
280
344
    Q_D(UiProxy);
291
355
                     d, SLOT(onRequestCompleted()));
292
356
    request->setInProgress(true);
293
357
 
294
 
    if (d->m_socket && d->m_socket->isValid()) {
 
358
    if (d->m_status == UiProxy::Ready) {
295
359
        d->sendRequest(requestId, request);
 
360
    } else if (d->m_status == UiProxy::Null) {
 
361
        d->startProcess();
296
362
    }
297
363
}
298
364