1 |
commit: 88f5d2ddef486a6ca915d2d7467e69461d4b1eff |
2 |
Author: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org> |
3 |
AuthorDate: Thu Apr 27 17:52:40 2017 +0000 |
4 |
Commit: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org> |
5 |
CommitDate: Thu Apr 27 18:14:43 2017 +0000 |
6 |
URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=88f5d2dd |
7 |
|
8 |
kde-apps/libkgapi: Fix 2FA, add USE=nls and missing DEPEND |
9 |
|
10 |
Package-Manager: Portage-2.3.3, Repoman-2.3.1 |
11 |
|
12 |
.../libkgapi/files/libkgapi-17.04.0-auth1.patch | 168 +++++++++++ |
13 |
.../libkgapi/files/libkgapi-17.04.0-auth2.patch | 36 +++ |
14 |
.../libkgapi/files/libkgapi-17.04.0-auth3.patch | 310 +++++++++++++++++++++ |
15 |
kde-apps/libkgapi/libkgapi-17.04.0-r1.ebuild | 36 +++ |
16 |
4 files changed, 550 insertions(+) |
17 |
|
18 |
diff --git a/kde-apps/libkgapi/files/libkgapi-17.04.0-auth1.patch b/kde-apps/libkgapi/files/libkgapi-17.04.0-auth1.patch |
19 |
new file mode 100644 |
20 |
index 00000000000..eb426465947 |
21 |
--- /dev/null |
22 |
+++ b/kde-apps/libkgapi/files/libkgapi-17.04.0-auth1.patch |
23 |
@@ -0,0 +1,168 @@ |
24 |
+From 68b89bce22d0da234345ccffb869ae6863592624 Mon Sep 17 00:00:00 2001 |
25 |
+From: =?UTF-8?q?Daniel=20Vr=C3=A1til?= <dvratil@×××.org> |
26 |
+Date: Thu, 27 Apr 2017 17:22:27 +0200 |
27 |
+Subject: [PATCH 1/3] Auth: Adapt to changes in Google OAuth token retrieval |
28 |
+ process |
29 |
+ |
30 |
+URLs and HTML code have changed a bit, which breaks authentication. Hopefully |
31 |
+they won't change it too often in the future. |
32 |
+--- |
33 |
+ src/core/ui/authwidget_p.cpp | 109 ++++++++++++++++++++++++------------------- |
34 |
+ src/core/ui/authwidget_p.h | 6 +++ |
35 |
+ 2 files changed, 67 insertions(+), 48 deletions(-) |
36 |
+ |
37 |
+diff --git a/src/core/ui/authwidget_p.cpp b/src/core/ui/authwidget_p.cpp |
38 |
+index 6de33f5..75d38cd 100644 |
39 |
+--- a/src/core/ui/authwidget_p.cpp |
40 |
++++ b/src/core/ui/authwidget_p.cpp |
41 |
+@@ -112,11 +112,35 @@ void AuthWidgetPrivate::emitError(const enum Error errCode, const QString& msg) |
42 |
+ |
43 |
+ void AuthWidgetPrivate::webviewUrlChanged(const QUrl &url) |
44 |
+ { |
45 |
+- qCDebug(KGAPIDebug) << url; |
46 |
++ qCDebug(KGAPIDebug) << "URLChange:" << url; |
47 |
+ |
48 |
+- /* Access token here - hide browser and tell user to wait until we |
49 |
+- * finish the authentication process ourselves */ |
50 |
+- if (url.host() == QLatin1String("accounts.google.com") && url.path() == QLatin1String("/o/oauth2/approval")) { |
51 |
++ if (!isGoogleHost(url)) { |
52 |
++ return; |
53 |
++ } |
54 |
++ |
55 |
++ // Username and password inputs are loaded dynamically, so we only get |
56 |
++ // urlChanged, but not urlFinished. |
57 |
++ if (isUsernameFrame(url)) { |
58 |
++#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) |
59 |
++ if (!username.isEmpty()) { |
60 |
++ webview->page()->runJavaScript(QStringLiteral("document.getElementById(\"identifierId\").value = \"%1\";").arg(username)); |
61 |
++ } |
62 |
++#endif |
63 |
++ } else if (isPasswordFrame(url)) { |
64 |
++#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) |
65 |
++ if (!password.isEmpty()) { |
66 |
++ webview->page()->runJavaScript(QStringLiteral("var elems = document.getElementsByTagName(\"input\");" |
67 |
++ "for (var i = 0; i < elems.length; i++) {" |
68 |
++ " if (elems[i].type == \"password\" && elems[i].name == \"password\") {" |
69 |
++ " elems[i].value = \"%1\";" |
70 |
++ " break;" |
71 |
++ " }" |
72 |
++ "}").arg(password)); |
73 |
++ } |
74 |
++#endif |
75 |
++ } else if (isTokenPage(url)) { |
76 |
++ /* Access token here - hide browser and tell user to wait until we |
77 |
++ * finish the authentication process ourselves */ |
78 |
+ webview->setVisible(false); |
79 |
+ progressbar->setVisible(false); |
80 |
+ label->setVisible(true); |
81 |
+@@ -131,57 +155,46 @@ void AuthWidgetPrivate::webviewFinished(bool ok) |
82 |
+ qCWarning(KGAPIDebug) << "Failed to load" << webview->url(); |
83 |
+ } |
84 |
+ |
85 |
+- QUrl url = webview->url(); |
86 |
+- qCDebug(KGAPIDebug) << url; |
87 |
+- |
88 |
+- if (url.host() == QLatin1String("accounts.google.com") && url.path() == QLatin1String("/ServiceLogin")) { |
89 |
+- if (username.isEmpty() && password.isEmpty()) { |
90 |
+- return; |
91 |
+- } |
92 |
+- |
93 |
+-#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) |
94 |
+- const auto js = QStringLiteral("document.getElementById(\"%1\").value = \"%2\";"); |
95 |
+- if (!username.isEmpty()) { |
96 |
+- webview->page()->runJavaScript(js.arg(QStringLiteral("Email"), username)); |
97 |
+- } |
98 |
+- |
99 |
+- if (!password.isEmpty()) { |
100 |
+- webview->page()->runJavaScript(js.arg(QStringLiteral("Passwd"), password)); |
101 |
+- } |
102 |
+-#endif |
103 |
++ const QUrl url = webview->url(); |
104 |
++ qCDebug(KGAPIDebug) << "URLFinished:" << url; |
105 |
+ |
106 |
++ if (!isGoogleHost(url)) { |
107 |
+ return; |
108 |
+ } |
109 |
+ |
110 |
+- if (url.host() == QLatin1String("accounts.google.com") && url.path() == QLatin1String("/o/oauth2/approval")) { |
111 |
+- QString title = webview->title(); |
112 |
+- QString token; |
113 |
+- |
114 |
+- if (title.startsWith(QLatin1String("success"), Qt::CaseInsensitive)) { |
115 |
+- int pos = title.indexOf(QLatin1String("code=")); |
116 |
+- /* Skip the 'code=' string as well */ |
117 |
+- token = title.mid (pos + 5); |
118 |
++ if (isTokenPage(url)) { |
119 |
++ const auto token = url.queryItemValue(QStringLiteral("approvalCode")); |
120 |
++ if (!token.isEmpty()) { |
121 |
++ qCDebug(KGAPIDebug) << "Got token: " << token; |
122 |
++ auto fetch = new KGAPI2::NewTokensFetchJob(token, apiKey, secretKey); |
123 |
++ connect(fetch, &Job::finished, this, &AuthWidgetPrivate::tokensReceived); |
124 |
+ } else { |
125 |
+- webview->page()->toHtml([title](const QString &html) { |
126 |
+- qCDebug(KGAPIDebug) << "Parsing token page failed. Title:" << title; |
127 |
+- qCDebug(KGAPIDebug) << html; |
128 |
+- }); |
129 |
++#if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) |
130 |
++ qCWarning(KGAPIDebug) << "Failed to parse token from URL, peaking into HTML..."; |
131 |
++ webview->page()->runJavaScript( |
132 |
++ QStringLiteral("document.getElementById(\"code\").value;"), |
133 |
++ [this](const QVariant &result) { |
134 |
++ const auto token = result.toString(); |
135 |
++ if (token.isEmpty()) { |
136 |
++ qCWarning(KGAPIDebug) << "Peaked into HTML, but cound not find token :("; |
137 |
++ webview->page()->toHtml([](const QString &html) { |
138 |
++ qCDebug(KGAPIDebug) << "Parsing token page failed"; |
139 |
++ qCDebug(KGAPIDebug) << html; |
140 |
++ }); |
141 |
++ emitError(AuthError, tr("Parsing token page failed.")); |
142 |
++ return; |
143 |
++ } |
144 |
++ qCDebug(KGAPIDebug) << "Peaked into HTML and found token: " << token; |
145 |
++ auto fetch = new KGAPI2::NewTokensFetchJob(token, apiKey, secretKey); |
146 |
++ connect(fetch, &Job::finished, this, &AuthWidgetPrivate::tokensReceived); |
147 |
++ }); |
148 |
++#else |
149 |
++ qCWarning(KGAPIDebug) << "Failed to parse token from URL!"; |
150 |
+ emitError(AuthError, tr("Parsing token page failed.")); |
151 |
+- return; |
152 |
+- } |
153 |
+- |
154 |
+- if (token.isEmpty()) { |
155 |
+- webview->page()->toHtml([](const QString &html) { |
156 |
+- qCDebug(KGAPIDebug) << "Failed to obtain token."; |
157 |
+- qCDebug(KGAPIRaw) << html; |
158 |
+- }); |
159 |
+- emitError(AuthError, tr("Failed to obtain token.")); |
160 |
+- return; |
161 |
++#endif |
162 |
+ } |
163 |
+- |
164 |
+- KGAPI2::NewTokensFetchJob *fetchJob = new KGAPI2::NewTokensFetchJob(token, apiKey, secretKey); |
165 |
+- connect(fetchJob, &Job::finished, |
166 |
+- this, &AuthWidgetPrivate::tokensReceived); |
167 |
++ } else { |
168 |
++ //qCDebug(KGAPIDebug) << "Unhandled page:" << url.host() << ", " << url.path(); |
169 |
+ } |
170 |
+ } |
171 |
+ |
172 |
+diff --git a/src/core/ui/authwidget_p.h b/src/core/ui/authwidget_p.h |
173 |
+index 673b0cb..9c488be 100644 |
174 |
+--- a/src/core/ui/authwidget_p.h |
175 |
++++ b/src/core/ui/authwidget_p.h |
176 |
+@@ -82,6 +82,12 @@ class Q_DECL_HIDDEN AuthWidgetPrivate: public QObject { |
177 |
+ void setupUi(); |
178 |
+ void setProgress(AuthWidget::Progress progress); |
179 |
+ |
180 |
++ bool isGoogleHost(const QUrl &url) const { return url.host() == QLatin1String("accounts.google.com"); } |
181 |
++ bool isSigninPage(const QUrl &url) const { return url.path() == QLatin1String("/signin/oauth"); } |
182 |
++ bool isUsernameFrame(const QUrl &url) { return url.path() == QLatin1String("/signin/oauth/identifier"); } |
183 |
++ bool isPasswordFrame(const QUrl &url) { return url.path() == QLatin1String("/signin/v2/challenge/pwd"); } |
184 |
++ bool isTokenPage(const QUrl &url) { return url.path() == QLatin1String("/o/oauth2/approval/v2"); } |
185 |
++ |
186 |
+ AuthWidget *q; |
187 |
+ |
188 |
+ friend class AuthWidget; |
189 |
+-- |
190 |
+2.12.2 |
191 |
+ |
192 |
|
193 |
diff --git a/kde-apps/libkgapi/files/libkgapi-17.04.0-auth2.patch b/kde-apps/libkgapi/files/libkgapi-17.04.0-auth2.patch |
194 |
new file mode 100644 |
195 |
index 00000000000..cba162a4f18 |
196 |
--- /dev/null |
197 |
+++ b/kde-apps/libkgapi/files/libkgapi-17.04.0-auth2.patch |
198 |
@@ -0,0 +1,36 @@ |
199 |
+From 5a20c7494f48da93914f50bbb54423ef540ef998 Mon Sep 17 00:00:00 2001 |
200 |
+From: =?UTF-8?q?Daniel=20Vr=C3=A1til?= <dvratil@×××.org> |
201 |
+Date: Thu, 27 Apr 2017 17:24:03 +0200 |
202 |
+Subject: [PATCH 2/3] Auth: don't store cookies |
203 |
+ |
204 |
+Don't store WebEngine cookies, otherwise Google will display the account |
205 |
+that user signed in with the last time, which may not be desirable. |
206 |
+--- |
207 |
+ src/core/ui/authwidget_p.cpp | 4 ++++ |
208 |
+ 1 file changed, 4 insertions(+) |
209 |
+ |
210 |
+diff --git a/src/core/ui/authwidget_p.cpp b/src/core/ui/authwidget_p.cpp |
211 |
+index 75d38cd..a51f4a9 100644 |
212 |
+--- a/src/core/ui/authwidget_p.cpp |
213 |
++++ b/src/core/ui/authwidget_p.cpp |
214 |
+@@ -26,6 +26,7 @@ |
215 |
+ #include "../../debug.h" |
216 |
+ |
217 |
+ #include <QWebEngineView> |
218 |
++#include <QWebEngineProfile> |
219 |
+ #include <QNetworkReply> |
220 |
+ #include <QContextMenuEvent> |
221 |
+ |
222 |
+@@ -36,6 +37,9 @@ using namespace KGAPI2; |
223 |
+ WebView::WebView(QWidget *parent) |
224 |
+ : QWebEngineView(parent) |
225 |
+ { |
226 |
++ // Don't store cookies, so that subsequent invocations of AuthJob won't remember |
227 |
++ // the previous accounts. |
228 |
++ QWebEngineProfile::defaultProfile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies); |
229 |
+ } |
230 |
+ |
231 |
+ |
232 |
+-- |
233 |
+2.12.2 |
234 |
+ |
235 |
|
236 |
diff --git a/kde-apps/libkgapi/files/libkgapi-17.04.0-auth3.patch b/kde-apps/libkgapi/files/libkgapi-17.04.0-auth3.patch |
237 |
new file mode 100644 |
238 |
index 00000000000..61d3b306bed |
239 |
--- /dev/null |
240 |
+++ b/kde-apps/libkgapi/files/libkgapi-17.04.0-auth3.patch |
241 |
@@ -0,0 +1,310 @@ |
242 |
+From 7b0934611ef72fb7e7c405813a1d2bb8b944dadc Mon Sep 17 00:00:00 2001 |
243 |
+From: =?UTF-8?q?Daniel=20Vr=C3=A1til?= <dvratil@×××.org> |
244 |
+Date: Thu, 27 Apr 2017 18:41:45 +0200 |
245 |
+Subject: [PATCH 3/3] Auth: add URL bar and SSL indicator to the authentication |
246 |
+ page |
247 |
+ |
248 |
+To increase trust-worthiness of the authentication dialog we now display |
249 |
+the URL and an SSL indicator above the webview. |
250 |
+--- |
251 |
+ src/core/ui/authwidget.cpp | 2 + |
252 |
+ src/core/ui/authwidget_p.cpp | 137 +++++++++++++++++++++++++++++++++++++++---- |
253 |
+ src/core/ui/authwidget_p.h | 25 ++++---- |
254 |
+ 3 files changed, 136 insertions(+), 28 deletions(-) |
255 |
+ |
256 |
+diff --git a/src/core/ui/authwidget.cpp b/src/core/ui/authwidget.cpp |
257 |
+index 18d2106..ac09b63 100644 |
258 |
+--- a/src/core/ui/authwidget.cpp |
259 |
++++ b/src/core/ui/authwidget.cpp |
260 |
+@@ -107,6 +107,8 @@ void AuthWidget::authenticate() |
261 |
+ |
262 |
+ qCDebug(KGAPIRaw) << "Requesting new token:" << url; |
263 |
+ |
264 |
++ d->sslIndicator->setVisible(true); |
265 |
++ d->urlEdit->setVisible(true); |
266 |
+ d->webview->setVisible(true); |
267 |
+ if (d->showProgressBar) { |
268 |
+ d->progressbar->setVisible(true); |
269 |
+diff --git a/src/core/ui/authwidget_p.cpp b/src/core/ui/authwidget_p.cpp |
270 |
+index a51f4a9..f732935 100644 |
271 |
+--- a/src/core/ui/authwidget_p.cpp |
272 |
++++ b/src/core/ui/authwidget_p.cpp |
273 |
+@@ -25,35 +25,79 @@ |
274 |
+ #include "private/newtokensfetchjob_p.h" |
275 |
+ #include "../../debug.h" |
276 |
+ |
277 |
+-#include <QWebEngineView> |
278 |
+ #include <QWebEngineProfile> |
279 |
+ #include <QNetworkReply> |
280 |
+ #include <QContextMenuEvent> |
281 |
+ |
282 |
++#include <QVBoxLayout> |
283 |
++#include <QLabel> |
284 |
++#include <QTimer> |
285 |
++#include <QMessageBox> |
286 |
++ |
287 |
+ #include <QDateTime> |
288 |
+ |
289 |
+ using namespace KGAPI2; |
290 |
+ |
291 |
+-WebView::WebView(QWidget *parent) |
292 |
+- : QWebEngineView(parent) |
293 |
++namespace |
294 |
+ { |
295 |
+- // Don't store cookies, so that subsequent invocations of AuthJob won't remember |
296 |
+- // the previous accounts. |
297 |
+- QWebEngineProfile::defaultProfile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies); |
298 |
+-} |
299 |
+ |
300 |
+- |
301 |
+-WebView::~WebView() |
302 |
++class WebView : public QWebEngineView |
303 |
+ { |
304 |
++ Q_OBJECT |
305 |
++public: |
306 |
++ explicit WebView(QWidget *parent = nullptr) |
307 |
++ : QWebEngineView(parent) |
308 |
++ { |
309 |
++ // Don't store cookies, so that subsequent invocations of AuthJob won't remember |
310 |
++ // the previous accounts. |
311 |
++ QWebEngineProfile::defaultProfile()->setPersistentCookiesPolicy(QWebEngineProfile::NoPersistentCookies); |
312 |
++ } |
313 |
+ |
314 |
+-} |
315 |
++ void contextMenuEvent(QContextMenuEvent *e) Q_DECL_OVERRIDE |
316 |
++ { |
317 |
++ // No menu |
318 |
++ e->accept(); |
319 |
++ } |
320 |
++}; |
321 |
+ |
322 |
+-void WebView::contextMenuEvent(QContextMenuEvent *e) |
323 |
++class WebPage : public QWebEnginePage |
324 |
+ { |
325 |
+- // No menu |
326 |
+- e->accept(); |
327 |
++ Q_OBJECT |
328 |
++public: |
329 |
++ explicit WebPage(QObject *parent = nullptr) |
330 |
++ : QWebEnginePage(parent) |
331 |
++ , mLastError(nullptr) |
332 |
++ { |
333 |
++ } |
334 |
++ |
335 |
++ QWebEngineCertificateError *lastCertificateError() const |
336 |
++ { |
337 |
++ return mLastError; |
338 |
++ } |
339 |
++ |
340 |
++ bool certificateError(const QWebEngineCertificateError &err) Q_DECL_OVERRIDE |
341 |
++ { |
342 |
++ if (mLastError) { |
343 |
++ delete mLastError; |
344 |
++ } |
345 |
++ mLastError = new QWebEngineCertificateError(err.error(), err.url(), err.isOverridable(), err.errorDescription()); |
346 |
++ Q_EMIT sslError(); |
347 |
++ |
348 |
++ return false; // don't let it through |
349 |
++ } |
350 |
++ |
351 |
++Q_SIGNALS: |
352 |
++ void sslError(); |
353 |
++ |
354 |
++private: |
355 |
++ QWebEngineCertificateError *mLastError; |
356 |
++}; |
357 |
++ |
358 |
+ } |
359 |
+ |
360 |
++ |
361 |
++ |
362 |
++ |
363 |
+ AuthWidgetPrivate::AuthWidgetPrivate(AuthWidget *parent): |
364 |
+ QObject(), |
365 |
+ showProgressBar(true), |
366 |
+@@ -67,6 +111,15 @@ AuthWidgetPrivate::~AuthWidgetPrivate() |
367 |
+ { |
368 |
+ } |
369 |
+ |
370 |
++void AuthWidgetPrivate::setSslIcon(const QString &iconName) |
371 |
++{ |
372 |
++ // FIXME: workaround for silly Breeze icons: the small 22x22 icons are |
373 |
++ // monochromatic, which is absolutely useless since we are trying to security |
374 |
++ // information here, so instead we force use the bigger 48x48 icons which |
375 |
++ // have colors and downscale them |
376 |
++ sslIndicator->setIcon(QIcon::fromTheme(iconName).pixmap(48)); |
377 |
++} |
378 |
++ |
379 |
+ void AuthWidgetPrivate::setupUi() |
380 |
+ { |
381 |
+ vbox = new QVBoxLayout(q); |
382 |
+@@ -79,6 +132,26 @@ void AuthWidgetPrivate::setupUi() |
383 |
+ label->setVisible(false); |
384 |
+ vbox->addWidget(label); |
385 |
+ |
386 |
++ auto hbox = new QHBoxLayout; |
387 |
++ hbox->setSpacing(0); |
388 |
++ sslIndicator = new QToolButton(q); |
389 |
++ connect(sslIndicator, &QToolButton::clicked, |
390 |
++ this, [this]() { |
391 |
++ auto page = qobject_cast<WebPage*>(webview->page()); |
392 |
++ if (auto err = page->lastCertificateError()) { |
393 |
++ QMessageBox msg; |
394 |
++ msg.setIconPixmap(QIcon::fromTheme(QStringLiteral("security-low")).pixmap(64)); |
395 |
++ msg.setText(err->errorDescription()); |
396 |
++ msg.addButton(QMessageBox::Ok); |
397 |
++ msg.exec(); |
398 |
++ } |
399 |
++ }); |
400 |
++ hbox->addWidget(sslIndicator); |
401 |
++ urlEdit = new QLineEdit(q); |
402 |
++ urlEdit->setReadOnly(true); |
403 |
++ hbox->addWidget(urlEdit); |
404 |
++ vbox->addLayout(hbox); |
405 |
++ |
406 |
+ progressbar = new QProgressBar(q); |
407 |
+ progressbar->setMinimum(0); |
408 |
+ progressbar->setMaximum(100); |
409 |
+@@ -87,6 +160,13 @@ void AuthWidgetPrivate::setupUi() |
410 |
+ |
411 |
+ webview = new WebView(q); |
412 |
+ |
413 |
++ auto webpage = new WebPage(webview); |
414 |
++ connect(webpage, &WebPage::sslError, |
415 |
++ this, [this]() { |
416 |
++ setSslIcon(QStringLiteral("security-low")); |
417 |
++ }); |
418 |
++ webview->setPage(webpage); |
419 |
++ |
420 |
+ vbox->addWidget(webview); |
421 |
+ connect(webview, &QWebEngineView::loadProgress, progressbar, &QProgressBar::setValue); |
422 |
+ connect(webview, &QWebEngineView::urlChanged, this, &AuthWidgetPrivate::webviewUrlChanged); |
423 |
+@@ -104,6 +184,8 @@ void AuthWidgetPrivate::setProgress(AuthWidget::Progress progress) |
424 |
+ void AuthWidgetPrivate::emitError(const enum Error errCode, const QString& msg) |
425 |
+ { |
426 |
+ label->setVisible(true); |
427 |
++ sslIndicator->setVisible(false); |
428 |
++ urlEdit->setVisible(false); |
429 |
+ webview->setVisible(false); |
430 |
+ progressbar->setVisible(false); |
431 |
+ |
432 |
+@@ -118,10 +200,33 @@ void AuthWidgetPrivate::webviewUrlChanged(const QUrl &url) |
433 |
+ { |
434 |
+ qCDebug(KGAPIDebug) << "URLChange:" << url; |
435 |
+ |
436 |
++ // Whoa! That should not happen! |
437 |
++ if (url.scheme() != QLatin1String("https")) { |
438 |
++ QTimer::singleShot(0, this, [this, url]() { |
439 |
++ QUrl sslUrl = url; |
440 |
++ sslUrl.setScheme(QStringLiteral("https")); |
441 |
++ webview->setUrl(sslUrl); |
442 |
++ }); |
443 |
++ return; |
444 |
++ } |
445 |
++ |
446 |
+ if (!isGoogleHost(url)) { |
447 |
++ // We handled SSL above, so we are secure. We are however outside of |
448 |
++ // accounts.google.com, which is a little suspicious in context of this class |
449 |
++ setSslIcon(QStringLiteral("security-medium")); |
450 |
+ return; |
451 |
+ } |
452 |
+ |
453 |
++ if (qobject_cast<WebPage*>(webview->page())->lastCertificateError()) { |
454 |
++ setSslIcon(QStringLiteral("security-low")); |
455 |
++ } else { |
456 |
++ // We have no way of obtaining current SSL certifiace from QWebEngine, but we |
457 |
++ // handled SSL and accounts.google.com cases above and QWebEngine did not report |
458 |
++ // any SSL error to us, so we can assume we are safe. |
459 |
++ setSslIcon(QStringLiteral("security-high")); |
460 |
++ } |
461 |
++ |
462 |
++ |
463 |
+ // Username and password inputs are loaded dynamically, so we only get |
464 |
+ // urlChanged, but not urlFinished. |
465 |
+ if (isUsernameFrame(url)) { |
466 |
+@@ -145,6 +250,8 @@ void AuthWidgetPrivate::webviewUrlChanged(const QUrl &url) |
467 |
+ } else if (isTokenPage(url)) { |
468 |
+ /* Access token here - hide browser and tell user to wait until we |
469 |
+ * finish the authentication process ourselves */ |
470 |
++ sslIndicator->setVisible(false); |
471 |
++ urlEdit->setVisible(false); |
472 |
+ webview->setVisible(false); |
473 |
+ progressbar->setVisible(false); |
474 |
+ label->setVisible(true); |
475 |
+@@ -160,6 +267,8 @@ void AuthWidgetPrivate::webviewFinished(bool ok) |
476 |
+ } |
477 |
+ |
478 |
+ const QUrl url = webview->url(); |
479 |
++ urlEdit->setText(url.toDisplayString(QUrl::PrettyDecoded)); |
480 |
++ urlEdit->setCursorPosition(0); |
481 |
+ qCDebug(KGAPIDebug) << "URLFinished:" << url; |
482 |
+ |
483 |
+ if (!isGoogleHost(url)) { |
484 |
+@@ -238,3 +347,5 @@ void AuthWidgetPrivate::accountInfoReceived(KGAPI2::Job* job) |
485 |
+ setProgress(AuthWidget::Finished); |
486 |
+ } |
487 |
+ |
488 |
++ |
489 |
++#include "authwidget_p.moc" |
490 |
+diff --git a/src/core/ui/authwidget_p.h b/src/core/ui/authwidget_p.h |
491 |
+index 9c488be..78b0e7f 100644 |
492 |
+--- a/src/core/ui/authwidget_p.h |
493 |
++++ b/src/core/ui/authwidget_p.h |
494 |
+@@ -26,27 +26,18 @@ |
495 |
+ #include "ui/authwidget.h" |
496 |
+ #include "types.h" |
497 |
+ |
498 |
++#include <QLineEdit> |
499 |
++#include <QToolButton> |
500 |
+ #include <QProgressBar> |
501 |
+-#include <QVBoxLayout> |
502 |
+ #include <QWebEngineView> |
503 |
+-#include <QLabel> |
504 |
++ |
505 |
++class QVBoxLayout; |
506 |
++class QLabel; |
507 |
+ |
508 |
+ namespace KGAPI2 { |
509 |
+ |
510 |
+ class Job; |
511 |
+ |
512 |
+-class WebView : public QWebEngineView |
513 |
+-{ |
514 |
+- Q_OBJECT |
515 |
+-public: |
516 |
+- explicit WebView(QWidget *parent=0); |
517 |
+- ~WebView(); |
518 |
+- |
519 |
+-protected: |
520 |
+- void contextMenuEvent(QContextMenuEvent *) Q_DECL_OVERRIDE; |
521 |
+-}; |
522 |
+- |
523 |
+- |
524 |
+ class Q_DECL_HIDDEN AuthWidgetPrivate: public QObject { |
525 |
+ |
526 |
+ Q_OBJECT |
527 |
+@@ -65,9 +56,11 @@ class Q_DECL_HIDDEN AuthWidgetPrivate: public QObject { |
528 |
+ QString apiKey; |
529 |
+ QString secretKey; |
530 |
+ |
531 |
++ QToolButton *sslIndicator; |
532 |
++ QLineEdit *urlEdit; |
533 |
+ QProgressBar *progressbar; |
534 |
+ QVBoxLayout *vbox; |
535 |
+- WebView *webview; |
536 |
++ QWebEngineView *webview; |
537 |
+ QLabel *label; |
538 |
+ |
539 |
+ private Q_SLOTS: |
540 |
+@@ -88,6 +81,8 @@ class Q_DECL_HIDDEN AuthWidgetPrivate: public QObject { |
541 |
+ bool isPasswordFrame(const QUrl &url) { return url.path() == QLatin1String("/signin/v2/challenge/pwd"); } |
542 |
+ bool isTokenPage(const QUrl &url) { return url.path() == QLatin1String("/o/oauth2/approval/v2"); } |
543 |
+ |
544 |
++ void setSslIcon(const QString &icon); |
545 |
++ |
546 |
+ AuthWidget *q; |
547 |
+ |
548 |
+ friend class AuthWidget; |
549 |
+-- |
550 |
+2.12.2 |
551 |
+ |
552 |
|
553 |
diff --git a/kde-apps/libkgapi/libkgapi-17.04.0-r1.ebuild b/kde-apps/libkgapi/libkgapi-17.04.0-r1.ebuild |
554 |
new file mode 100644 |
555 |
index 00000000000..d48cb19e0dc |
556 |
--- /dev/null |
557 |
+++ b/kde-apps/libkgapi/libkgapi-17.04.0-r1.ebuild |
558 |
@@ -0,0 +1,36 @@ |
559 |
+# Copyright 1999-2017 Gentoo Foundation |
560 |
+# Distributed under the terms of the GNU General Public License v2 |
561 |
+ |
562 |
+EAPI=6 |
563 |
+ |
564 |
+KDE_BLOCK_SLOT4="false" |
565 |
+KDE_TEST="true" |
566 |
+VIRTUALX_REQUIRED="test" |
567 |
+inherit kde5 |
568 |
+ |
569 |
+DESCRIPTION="Library for accessing Google calendar and contact resources" |
570 |
+HOMEPAGE="https://projects.kde.org/projects/extragear/libs/libkgapi" |
571 |
+ |
572 |
+LICENSE="LGPL-2.1+" |
573 |
+KEYWORDS="~amd64 ~x86" |
574 |
+IUSE="nls" |
575 |
+ |
576 |
+COMMON_DEPEND=" |
577 |
+ $(add_frameworks_dep kio) |
578 |
+ $(add_frameworks_dep kwindowsystem) |
579 |
+ $(add_kdeapps_dep kcalcore) |
580 |
+ $(add_kdeapps_dep kcontacts) |
581 |
+ $(add_qt_dep qtgui) |
582 |
+ $(add_qt_dep qtnetwork) |
583 |
+ $(add_qt_dep qtwebengine) |
584 |
+ $(add_qt_dep qtwidgets) |
585 |
+ $(add_qt_dep qtxml) |
586 |
+" |
587 |
+DEPEND="${COMMON_DEPEND} |
588 |
+ nls? ( $(add_qt_dep linguist-tools) ) |
589 |
+" |
590 |
+RDEPEND="${COMMON_DEPEND} |
591 |
+ !kde-apps/kdepim-l10n |
592 |
+" |
593 |
+ |
594 |
+PATCHES=( "${FILESDIR}"/${P}-auth{1,2,3}.patch ) |