Gentoo Archives: gentoo-commits

From: Andreas Sturmlechner <asturm@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: kde-apps/libkgapi/, kde-apps/libkgapi/files/
Date: Thu, 27 Apr 2017 18:15:08
Message-Id: 1493316883.88f5d2ddef486a6ca915d2d7467e69461d4b1eff.asturm@gentoo
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 )