Merge lp:~mardy/ubuntu-system-settings-online-accounts/qml-dialog into lp:~online-accounts/ubuntu-system-settings-online-accounts/master

Proposed by Alberto Mardegan
Status: Merged
Merged at revision: 203
Proposed branch: lp:~mardy/ubuntu-system-settings-online-accounts/qml-dialog
Merge into: lp:~online-accounts/ubuntu-system-settings-online-accounts/master
Diff against target: 588 lines (+492/-2)
7 files modified
debian/control (+1/-0)
online-accounts-ui/dialog-request.cpp (+286/-0)
online-accounts-ui/dialog-request.h (+54/-0)
online-accounts-ui/online-accounts-ui.pro (+3/-0)
online-accounts-ui/qml/SignOnUiDialog.qml (+115/-0)
online-accounts-ui/signonui-request.cpp (+32/-2)
online-accounts-ui/ui.qrc (+1/-0)
To merge this branch: bzr merge lp:~mardy/ubuntu-system-settings-online-accounts/qml-dialog
Reviewer Review Type Date Requested Status
David Barth (community) Approve
Review via email: mp+237970@code.launchpad.net

Commit message

Implement QML dialog for password queries

Authentication plugins can request SignOnUi to show a login form to the user. Support for this action is implemented by unity7's signon-ui, but was never implemented in this project.

Description of the change

Implement QML dialog for password queries

Authentication plugins can request SignOnUi to show a login form to the user. Support for this action is implemented by unity7's signon-ui, but was never implemented in this project.

Test case:
ubuntu-system-settings-online-accounts/password-query from https://wiki.ubuntu.com/Process/Merges/TestPlan/ubuntu-system-settings-online-accounts

To post a comment you must log in.
Revision history for this message
David Barth (dbarth) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'debian/control'
--- debian/control 2014-10-08 07:12:09 +0000
+++ debian/control 2014-10-10 13:24:04 +0000
@@ -6,6 +6,7 @@
6 pkg-config,6 pkg-config,
7 python3:any,7 python3:any,
8 libaccounts-qt5-dev (>= 1.13),8 libaccounts-qt5-dev (>= 1.13),
9 libapparmor-dev,
9 libclick-0.4-dev,10 libclick-0.4-dev,
10 libmirclient-dev [!powerpc !ppc64 !ppc64el],11 libmirclient-dev [!powerpc !ppc64 !ppc64el],
11 libnotify-dev,12 libnotify-dev,
1213
=== added file 'online-accounts-ui/dialog-request.cpp'
--- online-accounts-ui/dialog-request.cpp 1970-01-01 00:00:00 +0000
+++ online-accounts-ui/dialog-request.cpp 2014-10-10 13:24:04 +0000
@@ -0,0 +1,286 @@
1/*
2 * This file is part of online-accounts-ui
3 *
4 * Copyright (C) 2014 Canonical Ltd.
5 *
6 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
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 "dialog-request.h"
22
23#include "debug.h"
24#include "dialog.h"
25#include "globals.h"
26#include "i18n.h"
27
28#include <OnlineAccountsPlugin/request-handler.h>
29#include <QDir>
30#include <QQmlContext>
31#include <QQmlEngine>
32#include <SignOn/uisessiondata_priv.h>
33
34using namespace SignOnUi;
35
36/* These fields are temporarily defined here; they'll be eventually moved to
37 * signond's include files. */
38#define SSOUI_KEY_USERNAME_TEXT QLatin1String("UserNameText")
39#define SSOUI_KEY_PASSWORD_TEXT QLatin1String("PasswordText")
40#define SSOUI_KEY_REGISTER_URL QLatin1String("RegisterUrl")
41#define SSOUI_KEY_REGISTER_TEXT QLatin1String("RegisterText")
42#define SSOUI_KEY_LOGIN_TEXT QLatin1String("LoginText")
43
44namespace SignOnUi {
45
46class DialogRequestPrivate: public QObject
47{
48 Q_OBJECT
49 Q_DECLARE_PUBLIC(DialogRequest)
50 Q_PROPERTY(QString title READ title CONSTANT)
51 Q_PROPERTY(QString userName READ userName WRITE setUserName \
52 NOTIFY userNameChanged)
53 Q_PROPERTY(QString password READ password WRITE setPassword \
54 NOTIFY passwordChanged)
55 Q_PROPERTY(QString userNameText READ userNameText CONSTANT)
56 Q_PROPERTY(QString passwordText READ passwordText CONSTANT)
57 Q_PROPERTY(QString message READ message CONSTANT)
58 Q_PROPERTY(bool queryUserName READ queryUserName CONSTANT)
59 Q_PROPERTY(bool queryPassword READ queryPassword CONSTANT)
60 Q_PROPERTY(QUrl forgotPasswordUrl READ forgotPasswordUrl CONSTANT)
61 Q_PROPERTY(QString forgotPasswordText READ forgotPasswordText CONSTANT)
62 Q_PROPERTY(QUrl registerUrl READ registerUrl CONSTANT)
63 Q_PROPERTY(QString registerText READ registerText CONSTANT)
64 Q_PROPERTY(QString loginText READ loginText CONSTANT)
65
66public:
67 DialogRequestPrivate(DialogRequest *request);
68 ~DialogRequestPrivate();
69
70 void start();
71
72 QString title() const { return m_title; }
73 void setUserName(const QString &userName);
74 QString userName() const { return m_userName; }
75 void setPassword(const QString &password);
76 QString password() const { return m_password; }
77 QString userNameText() const { return m_userNameText; }
78 QString passwordText() const { return m_passwordText; }
79 QString message() const { return m_message; }
80 bool queryUserName() const { return m_queryUsername; }
81 bool queryPassword() const { return m_queryPassword; }
82 QUrl forgotPasswordUrl() const { return m_forgotPasswordUrl; }
83 QString forgotPasswordText() const { return m_forgotPasswordText; }
84 QUrl registerUrl() const { return m_registerUrl; }
85 QString registerText() const { return m_registerText; }
86 QString loginText() const { return m_loginText; }
87
88public Q_SLOTS:
89 void cancel();
90 void accept();
91
92Q_SIGNALS:
93 void userNameChanged();
94 void passwordChanged();
95
96private Q_SLOTS:
97 void onFinished();
98
99private:
100 void closeView();
101
102private:
103 Dialog *m_dialog;
104 QString m_title;
105 QString m_userName;
106 QString m_password;
107 QString m_userNameText;
108 QString m_passwordText;
109 QString m_message;
110 bool m_queryUsername;
111 bool m_queryPassword;
112 QUrl m_forgotPasswordUrl;
113 QString m_forgotPasswordText;
114 QUrl m_registerUrl;
115 QString m_registerText;
116 QString m_loginText;
117 mutable DialogRequest *q_ptr;
118};
119
120} // namespace
121
122DialogRequestPrivate::DialogRequestPrivate(DialogRequest *request):
123 QObject(request),
124 m_dialog(0),
125 m_queryUsername(false),
126 m_queryPassword(false),
127 q_ptr(request)
128{
129 const QVariantMap &params = q_ptr->parameters();
130
131 if (params.contains(SSOUI_KEY_TITLE)) {
132 m_title = params[SSOUI_KEY_TITLE].toString();
133 } else if (params.contains(SSOUI_KEY_CAPTION)) {
134 m_title = OnlineAccountsUi::_("Web authentication for %1",
135 SIGNONUI_I18N_DOMAIN).
136 arg(params[SSOUI_KEY_CAPTION].toString());
137 } else {
138 m_title = OnlineAccountsUi::_("Web authentication",
139 SIGNONUI_I18N_DOMAIN);
140 }
141
142 m_queryUsername = params.value(SSOUI_KEY_QUERYUSERNAME, false).toBool();
143 m_userName = params.value(SSOUI_KEY_USERNAME).toString();
144 m_userNameText = params.value(SSOUI_KEY_USERNAME_TEXT).toString();
145 if (m_userNameText.isEmpty()) {
146 m_userNameText = OnlineAccountsUi::_("Username:",
147 SIGNONUI_I18N_DOMAIN);
148 }
149
150 m_queryPassword = params.value(SSOUI_KEY_QUERYPASSWORD, false).toBool();
151 m_password = params.value(SSOUI_KEY_PASSWORD).toString();
152 m_passwordText = params.value(SSOUI_KEY_PASSWORD_TEXT).toString();
153 if (m_passwordText.isEmpty()) {
154 m_passwordText = OnlineAccountsUi::_("Password:",
155 SIGNONUI_I18N_DOMAIN);
156 }
157
158
159 m_message = params.value(SSOUI_KEY_MESSAGE).toString();
160
161 m_forgotPasswordUrl =
162 QUrl(params.value(SSOUI_KEY_FORGOTPASSWORDURL).toString());
163 m_forgotPasswordText = params.value(SSOUI_KEY_FORGOTPASSWORD).toString();
164
165 m_registerUrl =
166 QUrl(params.value(SSOUI_KEY_REGISTER_URL).toString());
167 m_registerText = params.value(SSOUI_KEY_REGISTER_TEXT).toString();
168
169 m_loginText = params.value(SSOUI_KEY_LOGIN_TEXT).toString();
170 if (m_loginText.isEmpty()) {
171 m_loginText = OnlineAccountsUi::_("Sign in");
172 }
173}
174
175DialogRequestPrivate::~DialogRequestPrivate()
176{
177 closeView();
178 delete m_dialog;
179}
180
181void DialogRequestPrivate::start()
182{
183 Q_Q(DialogRequest);
184
185 const QVariantMap &params = q->parameters();
186 DEBUG() << params;
187
188 if (!q->hasHandler()) {
189 m_dialog = new Dialog;
190 m_dialog->setTitle(m_title);
191
192 QObject::connect(m_dialog, SIGNAL(finished(int)),
193 this, SLOT(onFinished()));
194
195 m_dialog->engine()->addImportPath(PLUGIN_PRIVATE_MODULE_DIR);
196 m_dialog->rootContext()->setContextProperty("request", this);
197 m_dialog->setSource(QUrl("qrc:/qml/SignOnUiDialog.qml"));
198 q->setWindow(m_dialog);
199 } else {
200 DEBUG() << "Setting request on handler";
201 q->handler()->setRequest(this);
202 }
203}
204
205void DialogRequestPrivate::accept()
206{
207 DEBUG() << "User accepted";
208 onFinished();
209}
210
211void DialogRequestPrivate::cancel()
212{
213 Q_Q(DialogRequest);
214
215 DEBUG() << "User requested to cancel";
216 q->setCanceled();
217 closeView();
218}
219
220void DialogRequestPrivate::setUserName(const QString &userName)
221{
222 if (userName == m_userName) return;
223 m_userName = userName;
224 Q_EMIT userNameChanged();
225}
226
227void DialogRequestPrivate::setPassword(const QString &password)
228{
229 if (password == m_password) return;
230 m_password = password;
231 Q_EMIT passwordChanged();
232}
233
234void DialogRequestPrivate::onFinished()
235{
236 Q_Q(DialogRequest);
237
238 DEBUG() << "Dialog closed";
239
240 QVariantMap reply;
241
242 if (m_queryUsername) {
243 reply[SSOUI_KEY_USERNAME] = m_userName;
244 }
245 if (m_queryPassword) {
246 reply[SSOUI_KEY_PASSWORD] = m_password;
247 }
248
249 closeView();
250
251 q->setResult(reply);
252}
253
254void DialogRequestPrivate::closeView()
255{
256 Q_Q(DialogRequest);
257
258 if (q->hasHandler()) {
259 q->handler()->setRequest(0);
260 } else if (m_dialog) {
261 m_dialog->close();
262 }
263}
264
265DialogRequest::DialogRequest(int id,
266 const QString &clientProfile,
267 const QVariantMap &parameters,
268 QObject *parent):
269 Request(id, clientProfile, parameters, parent),
270 d_ptr(new DialogRequestPrivate(this))
271{
272}
273
274DialogRequest::~DialogRequest()
275{
276}
277
278void DialogRequest::start()
279{
280 Q_D(DialogRequest);
281
282 Request::start();
283 d->start();
284}
285
286#include "dialog-request.moc"
0287
=== added file 'online-accounts-ui/dialog-request.h'
--- online-accounts-ui/dialog-request.h 1970-01-01 00:00:00 +0000
+++ online-accounts-ui/dialog-request.h 2014-10-10 13:24:04 +0000
@@ -0,0 +1,54 @@
1/*
2 * This file is part of online-accounts-ui
3 *
4 * Copyright (C) 2014 Canonical Ltd.
5 *
6 * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
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#ifndef SIGNON_UI_DIALOG_REQUEST_H
22#define SIGNON_UI_DIALOG_REQUEST_H
23
24#include "signonui-request.h"
25
26#include <QObject>
27
28namespace SignOnUi {
29
30class DialogRequestPrivate;
31
32class DialogRequest: public Request
33{
34 Q_OBJECT
35
36public:
37 explicit DialogRequest(int id,
38 const QString &clientProfile,
39 const QVariantMap &parameters,
40 QObject *parent = 0);
41 ~DialogRequest();
42
43 // reimplemented virtual methods
44 void start();
45
46private:
47 DialogRequestPrivate *d_ptr;
48 Q_DECLARE_PRIVATE(DialogRequest)
49};
50
51} // namespace
52
53#endif // SIGNON_UI_DIALOG_REQUEST_H
54
055
=== modified file 'online-accounts-ui/online-accounts-ui.pro'
--- online-accounts-ui/online-accounts-ui.pro 2014-10-09 12:24:45 +0000
+++ online-accounts-ui/online-accounts-ui.pro 2014-10-10 13:24:04 +0000
@@ -17,6 +17,7 @@
1717
18PKGCONFIG += \18PKGCONFIG += \
19 accounts-qt5 \19 accounts-qt5 \
20 libapparmor \
20 libnotify \21 libnotify \
21 libsignon-qt5 \22 libsignon-qt5 \
22 signon-plugins-common23 signon-plugins-common
@@ -44,6 +45,7 @@
44 browser-request.cpp \45 browser-request.cpp \
45 debug.cpp \46 debug.cpp \
46 dialog.cpp \47 dialog.cpp \
48 dialog-request.cpp \
47 i18n.cpp \49 i18n.cpp \
48 ipc.cpp \50 ipc.cpp \
49 main.cpp \51 main.cpp \
@@ -59,6 +61,7 @@
59 browser-request.h \61 browser-request.h \
60 debug.h \62 debug.h \
61 dialog.h \63 dialog.h \
64 dialog-request.h \
62 i18n.h \65 i18n.h \
63 ipc.h \66 ipc.h \
64 notification.h \67 notification.h \
6568
=== added file 'online-accounts-ui/qml/SignOnUiDialog.qml'
--- online-accounts-ui/qml/SignOnUiDialog.qml 1970-01-01 00:00:00 +0000
+++ online-accounts-ui/qml/SignOnUiDialog.qml 2014-10-10 13:24:04 +0000
@@ -0,0 +1,115 @@
1import QtQuick 2.0
2import Ubuntu.Components 0.1
3import Ubuntu.Components.ListItems 0.1 as ListItem
4import Ubuntu.OnlineAccounts.Plugin 1.0
5
6MainView {
7 id: root
8
9 property var signonRequest: request
10
11 width: units.gu(60)
12 height: units.gu(90)
13
14 Page {
15 title: signonRequest.title
16
17 Column {
18 id: loginForm
19 anchors.left: parent.left
20 anchors.right: parent.right
21
22 ListItem.Caption {
23 visible: signonRequest.message !== ""
24 text: signonRequest.message
25 }
26
27 Label {
28 id: userNameLabel
29 visible: signonRequest.queryUserName
30 text: signonRequest.userNameText
31 }
32
33 TextField {
34 id: userNameField
35 visible: signonRequest.queryUserName
36 text: signonRequest.userName
37 onTextChanged: signonRequest.userName = text
38 }
39
40 Column {
41 anchors.left: parent.left
42 anchors.right: parent.right
43 visible: signonRequest.queryPassword
44
45 Label {
46 id: passwordLabel
47 text: signonRequest.passwordText
48 }
49
50 TextField {
51 id: passwordField
52 text: signonRequest.password
53 echoMode: TextInput.Password
54 onTextChanged: signonRequest.password = text
55 Keys.onReturnPressed: signonRequest.accept()
56 }
57 Label {
58 visible: signonRequest.forgotPasswordUrl.toString() !== ""
59 text: "<a href=\"" + signonRequest.forgotPasswordUrl + "\">" +
60 signonRequest.forgotPasswordText + "</a>"
61 }
62 }
63 }
64
65 Item {
66 anchors.left: parent.left
67 anchors.right: parent.right
68 anchors.top: loginForm.bottom
69 anchors.bottom: pageFooter.top
70
71 Row {
72 height: childrenRect.height
73 anchors.left: parent.left
74 anchors.right: parent.right
75 anchors.bottom: parent.bottom
76 spacing: units.gu(1)
77
78 Button {
79 text: i18n.dtr("ubuntu-system-settings-online-accounts", "Cancel")
80 width: (parent.width / 2) - 0.5 * parent.spacing
81 onClicked: signonRequest.cancel()
82 }
83
84 Button {
85 text: signonRequest.loginText
86 width: (parent.width / 2) - 0.5 * parent.spacing
87 onClicked: signonRequest.accept()
88 }
89 }
90 }
91
92 Item {
93 id: pageFooter
94 anchors.left: parent.left
95 anchors.right: parent.right
96 anchors.bottom: osk.top
97 visible: signonRequest.registerUrl.toString() !== ""
98
99 ListItem.ThinDivider {
100 anchors.bottom: registerUrlLabel.top
101 }
102
103 Label {
104 anchors.bottom: parent.bottom
105 id: registerUrlLabel
106 text: "<a href=\"" + signonRequest.registerUrl + "\">" +
107 signonRequest.registerText + "</a>"
108 }
109 }
110
111 KeyboardRectangle {
112 id: osk
113 }
114 }
115}
0116
=== modified file 'online-accounts-ui/signonui-request.cpp'
--- online-accounts-ui/signonui-request.cpp 2014-10-09 12:24:45 +0000
+++ online-accounts-ui/signonui-request.cpp 2014-10-10 13:24:04 +0000
@@ -22,6 +22,7 @@
2222
23#include "browser-request.h"23#include "browser-request.h"
24#include "debug.h"24#include "debug.h"
25#include "dialog-request.h"
25#include "globals.h"26#include "globals.h"
26#include "notification.h"27#include "notification.h"
2728
@@ -35,6 +36,7 @@
35#include <QPointer>36#include <QPointer>
36#include <SignOn/uisessiondata.h>37#include <SignOn/uisessiondata.h>
37#include <SignOn/uisessiondata_priv.h>38#include <SignOn/uisessiondata_priv.h>
39#include <sys/apparmor.h>
3840
39using namespace SignOnUi;41using namespace SignOnUi;
4042
@@ -203,16 +205,44 @@
203 return new SignOnUi::BrowserRequest(id, clientProfile,205 return new SignOnUi::BrowserRequest(id, clientProfile,
204 parameters, parent);206 parameters, parent);
205 } else {207 } else {
206 return 0; // TODO new DialogRequest(connection, message, parameters, parent);208 return new SignOnUi::DialogRequest(id, clientProfile,
209 parameters, parent);
207 }210 }
208}211}
209#endif212#endif
210213
214static QString findClientProfile(const QString &clientProfile,
215 const QVariantMap &parameters)
216{
217 QString profile = clientProfile;
218 /* If the request is coming on the SignOnUi interface from an
219 * unconfined process and it carries the SSOUI_KEY_PID key, it means that
220 * it's coming from signond. In that case, we want to know what was the
221 * client which originated the call.
222 */
223 if (profile == "unconfined" &&
224 parameters.contains(SSOUI_KEY_PID)) {
225 pid_t pid = parameters.value(SSOUI_KEY_PID).toUInt();
226 char *con = NULL, *mode = NULL;
227 int ret = aa_gettaskcon(pid, &con, &mode);
228 if (Q_LIKELY(ret >= 0)) {
229 profile = QString::fromUtf8(con);
230 /* libapparmor allocates "con" and "mode" in a single allocation,
231 * so freeing "con" is actually freeing both. */
232 free(con);
233 } else {
234 qWarning() << "Couldn't get apparmor profile of PID" << pid;
235 }
236 }
237 return profile;
238}
239
211Request::Request(int id,240Request::Request(int id,
212 const QString &clientProfile,241 const QString &clientProfile,
213 const QVariantMap &parameters,242 const QVariantMap &parameters,
214 QObject *parent):243 QObject *parent):
215 OnlineAccountsUi::Request(SIGNONUI_INTERFACE, id, clientProfile,244 OnlineAccountsUi::Request(SIGNONUI_INTERFACE, id,
245 findClientProfile(clientProfile, parameters),
216 parameters, parent),246 parameters, parent),
217 d_ptr(new RequestPrivate(this))247 d_ptr(new RequestPrivate(this))
218{248{
219249
=== modified file 'online-accounts-ui/ui.qrc'
--- online-accounts-ui/ui.qrc 2014-08-13 14:39:53 +0000
+++ online-accounts-ui/ui.qrc 2014-10-10 13:24:04 +0000
@@ -3,6 +3,7 @@
3 <file>qml/AccountCreationPage.qml</file>3 <file>qml/AccountCreationPage.qml</file>
4 <file>qml/AuthorizationPage.qml</file>4 <file>qml/AuthorizationPage.qml</file>
5 <file>qml/ProviderRequest.qml</file>5 <file>qml/ProviderRequest.qml</file>
6 <file>qml/SignOnUiDialog.qml</file>
6 <file>qml/SignOnUiPage.qml</file>7 <file>qml/SignOnUiPage.qml</file>
7</qresource>8</qresource>
8</RCC>9</RCC>

Subscribers

People subscribed via source and target branches