~mardy/ubuntu-system-settings-online-accounts/master

« back to all changes in this revision

Viewing changes to online-accounts-ui/ui-server.cpp

  • Committer: Alberto Mardegan
  • Date: 2014-08-13 14:44:09 UTC
  • mfrom: (129.1.7 headless-service)
  • Revision ID: alberto.mardegan@canonical.com-20140813144409-c88fg9u922le83cx
Move the UI into a separate process

Introduce online-accounts-service as a UI-less DBus service which acts as a
dispatcher for authentication and authorization requests; the requests
themselves are processed by a subprocess, online-accounts-ui, of which multiple
instances can exists (each instance having single window).

This is the first step towards implementing trust session support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2014 Canonical Ltd.
 
3
 *
 
4
 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
 
5
 *
 
6
 * This file is part of online-accounts-ui
 
7
 *
 
8
 * This program is free software: you can redistribute it and/or modify it
 
9
 * under the terms of the GNU General Public License version 3, as published
 
10
 * by the Free Software Foundation.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful, but
 
13
 * WITHOUT ANY WARRANTY; without even the implied warranties of
 
14
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
 
15
 * PURPOSE.  See the GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License along
 
18
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
 
 
21
#include "debug.h"
 
22
#include "ipc.h"
 
23
#include "request.h"
 
24
#include "request-handler.h"
 
25
#include "signonui-request.h"
 
26
#include "ui-server.h"
 
27
 
 
28
#include <QLocalSocket>
 
29
#include <QtQml>
 
30
#include <SignOn/uisessiondata_priv.h>
 
31
 
 
32
using namespace OnlineAccountsUi;
 
33
 
 
34
static UiServer *m_instance = 0;
 
35
 
 
36
namespace OnlineAccountsUi {
 
37
 
 
38
class UiServerPrivate: public QObject
 
39
{
 
40
    Q_OBJECT
 
41
    Q_DECLARE_PUBLIC(UiServer)
 
42
 
 
43
public:
 
44
    inline UiServerPrivate(const QString &address, UiServer *pluginServer);
 
45
    inline ~UiServerPrivate();
 
46
 
 
47
    bool setupSocket();
 
48
    bool init();
 
49
    void sendOperation(const QVariantMap &data);
 
50
 
 
51
private Q_SLOTS:
 
52
    void onDataReady(QByteArray &data);
 
53
    void onRequestCompleted();
 
54
 
 
55
private:
 
56
    QLocalSocket m_socket;
 
57
    OnlineAccountsUi::Ipc m_ipc;
 
58
    mutable UiServer *q_ptr;
 
59
};
 
60
 
 
61
} // namespace
 
62
 
 
63
UiServerPrivate::UiServerPrivate(const QString &address,
 
64
                                 UiServer *pluginServer):
 
65
    QObject(pluginServer),
 
66
    q_ptr(pluginServer)
 
67
{
 
68
    QObject::connect(&m_ipc, SIGNAL(dataReady(QByteArray &)),
 
69
                     this, SLOT(onDataReady(QByteArray &)));
 
70
    QObject::connect(&m_socket, SIGNAL(disconnected()),
 
71
                     q_ptr, SIGNAL(finished()));
 
72
    m_socket.connectToServer(address);
 
73
}
 
74
 
 
75
UiServerPrivate::~UiServerPrivate()
 
76
{
 
77
    DEBUG();
 
78
}
 
79
 
 
80
void UiServerPrivate::sendOperation(const QVariantMap &data)
 
81
{
 
82
    QByteArray ba;
 
83
    QDataStream stream(&ba, QIODevice::WriteOnly);
 
84
    stream << data;
 
85
    m_ipc.write(ba);
 
86
}
 
87
 
 
88
void UiServerPrivate::onDataReady(QByteArray &data)
 
89
{
 
90
    Q_Q(UiServer);
 
91
 
 
92
    QVariantMap map;
 
93
    QDataStream stream(&data, QIODevice::ReadOnly);
 
94
    stream >> map;
 
95
 
 
96
    DEBUG() << map;
 
97
 
 
98
    QString code = map.value(OAU_OPERATION_CODE).toString();
 
99
    if (code == OAU_OPERATION_CODE_PROCESS) {
 
100
        QVariantMap parameters = map[OAU_OPERATION_DATA].toMap();
 
101
        Request *request =
 
102
            Request::newRequest(map[OAU_OPERATION_INTERFACE].toString(),
 
103
                                map[OAU_OPERATION_ID].toInt(),
 
104
                                map[OAU_OPERATION_CLIENT_PROFILE].toString(),
 
105
                                parameters,
 
106
                                this);
 
107
        QObject::connect(request, SIGNAL(completed()),
 
108
                         this, SLOT(onRequestCompleted()));
 
109
 
 
110
        /* Check if a RequestHandler has been setup to handle this request. If
 
111
         * so, bing the request object to the handler and start the request
 
112
         * immediately. */
 
113
        SignOnUi::Request *signonRequest =
 
114
            qobject_cast<SignOnUi::Request*>(request);
 
115
        if (signonRequest) {
 
116
            SignOnUi::RequestHandler *handler =
 
117
                SignOnUi::RequestHandler::findMatching(parameters);
 
118
            if (handler) {
 
119
                signonRequest->setHandler(handler);
 
120
            }
 
121
        }
 
122
        request->start();
 
123
    } else {
 
124
        qWarning() << "Invalid operation code: " << code;
 
125
    }
 
126
}
 
127
 
 
128
void UiServerPrivate::onRequestCompleted()
 
129
{
 
130
    Request *request = qobject_cast<Request*>(sender());
 
131
    request->disconnect(this);
 
132
    request->deleteLater();
 
133
 
 
134
    if (request->errorName().isEmpty()) {
 
135
        QVariantMap operation;
 
136
        operation.insert(OAU_OPERATION_CODE,
 
137
                         OAU_OPERATION_CODE_REQUEST_FINISHED);
 
138
        operation.insert(OAU_OPERATION_ID, request->id());
 
139
        operation.insert(OAU_OPERATION_DATA, request->result());
 
140
        operation.insert(OAU_OPERATION_INTERFACE, request->interface());
 
141
        sendOperation(operation);
 
142
    } else {
 
143
        QVariantMap operation;
 
144
        operation.insert(OAU_OPERATION_CODE,
 
145
                         OAU_OPERATION_CODE_REQUEST_FAILED);
 
146
        operation.insert(OAU_OPERATION_ID, request->id());
 
147
        operation.insert(OAU_OPERATION_INTERFACE, request->interface());
 
148
        operation.insert(OAU_OPERATION_ERROR_NAME, request->errorName());
 
149
        operation.insert(OAU_OPERATION_ERROR_MESSAGE, request->errorMessage());
 
150
        sendOperation(operation);
 
151
    }
 
152
}
 
153
 
 
154
bool UiServerPrivate::init()
 
155
{
 
156
    if (Q_UNLIKELY(!m_socket.waitForConnected())) return false;
 
157
 
 
158
    m_ipc.setChannels(&m_socket, &m_socket);
 
159
    return true;
 
160
}
 
161
 
 
162
UiServer::UiServer(const QString &address, QObject *parent):
 
163
    QObject(parent),
 
164
    d_ptr(new UiServerPrivate(address, this))
 
165
{
 
166
    m_instance = this;
 
167
 
 
168
    qmlRegisterType<SignOnUi::RequestHandler>("Ubuntu.OnlineAccounts.Plugin",
 
169
                                              1, 0, "RequestHandler");
 
170
}
 
171
 
 
172
UiServer::~UiServer()
 
173
{
 
174
    m_instance = 0;
 
175
}
 
176
 
 
177
UiServer *UiServer::instance()
 
178
{
 
179
    return m_instance;
 
180
}
 
181
 
 
182
bool UiServer::init()
 
183
{
 
184
    Q_D(UiServer);
 
185
    return d->init();
 
186
}
 
187
 
 
188
void UiServer::registerHandler(SignOnUi::RequestHandler *handler)
 
189
{
 
190
    Q_D(UiServer);
 
191
 
 
192
    QVariantMap operation;
 
193
    operation.insert(OAU_OPERATION_CODE,
 
194
                     OAU_OPERATION_CODE_REGISTER_HANDLER);
 
195
    operation.insert(OAU_OPERATION_HANDLER_ID, handler->matchId());
 
196
    d->sendOperation(operation);
 
197
}
 
198
 
 
199
#include "ui-server.moc"