Changeset View
Standalone View
src/core/ui/authwidget_p.cpp
Show All 22 Lines | |||||
23 | #include "accountinfo/accountinfo.h" | 23 | #include "accountinfo/accountinfo.h" | ||
24 | #include "accountinfo/accountinfofetchjob.h" | 24 | #include "accountinfo/accountinfofetchjob.h" | ||
25 | #include "private/newtokensfetchjob_p.h" | 25 | #include "private/newtokensfetchjob_p.h" | ||
26 | #include "../../debug.h" | 26 | #include "../../debug.h" | ||
27 | 27 | | |||
28 | #include <QWebEngineProfile> | 28 | #include <QWebEngineProfile> | ||
29 | #include <QContextMenuEvent> | 29 | #include <QContextMenuEvent> | ||
30 | 30 | | |||
31 | #include <QtGlobal> | ||||
31 | #include <QVBoxLayout> | 32 | #include <QVBoxLayout> | ||
32 | #include <QLabel> | 33 | #include <QLabel> | ||
33 | #include <QTimer> | 34 | #include <QTimer> | ||
34 | #include <QMessageBox> | 35 | #include <QMessageBox> | ||
36 | #include <QAbstractSocket> | ||||
35 | 37 | | |||
36 | #include <QDateTime> | 38 | #include <QDateTime> | ||
37 | 39 | | |||
38 | using namespace KGAPI2; | 40 | using namespace KGAPI2; | ||
39 | 41 | | |||
40 | namespace | 42 | namespace | ||
41 | { | 43 | { | ||
42 | 44 | | |||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Line(s) | 165 | connect(webpage, &WebPage::sslError, | |||
164 | this, [this]() { | 166 | this, [this]() { | ||
165 | setSslIcon(QStringLiteral("security-low")); | 167 | setSslIcon(QStringLiteral("security-low")); | ||
166 | }); | 168 | }); | ||
167 | webview->setPage(webpage); | 169 | webview->setPage(webpage); | ||
168 | 170 | | |||
169 | vbox->addWidget(webview); | 171 | vbox->addWidget(webview); | ||
170 | connect(webview, &QWebEngineView::loadProgress, progressbar, &QProgressBar::setValue); | 172 | connect(webview, &QWebEngineView::loadProgress, progressbar, &QProgressBar::setValue); | ||
171 | connect(webview, &QWebEngineView::urlChanged, this, &AuthWidgetPrivate::webviewUrlChanged); | 173 | connect(webview, &QWebEngineView::urlChanged, this, &AuthWidgetPrivate::webviewUrlChanged); | ||
172 | connect(webview, &QWebEngineView::loadFinished, this, &AuthWidgetPrivate::webviewFinished); | | |||
173 | } | 174 | } | ||
174 | 175 | | |||
175 | void AuthWidgetPrivate::setProgress(AuthWidget::Progress progress) | 176 | void AuthWidgetPrivate::setProgress(AuthWidget::Progress progress) | ||
176 | { | 177 | { | ||
177 | qCDebug(KGAPIDebug) << progress; | 178 | qCDebug(KGAPIDebug) << progress; | ||
178 | this->progress = progress; | 179 | this->progress = progress; | ||
179 | Q_EMIT q->progress(progress); | 180 | Q_EMIT q->progress(progress); | ||
180 | } | 181 | } | ||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Line(s) | 237 | if (!password.isEmpty()) { | |||
237 | webview->page()->runJavaScript(QStringLiteral("var elems = document.getElementsByTagName(\"input\");" | 238 | webview->page()->runJavaScript(QStringLiteral("var elems = document.getElementsByTagName(\"input\");" | ||
238 | "for (var i = 0; i < elems.length; i++) {" | 239 | "for (var i = 0; i < elems.length; i++) {" | ||
239 | " if (elems[i].type == \"password\" && elems[i].name == \"password\") {" | 240 | " if (elems[i].type == \"password\" && elems[i].name == \"password\") {" | ||
240 | " elems[i].value = \"%1\";" | 241 | " elems[i].value = \"%1\";" | ||
241 | " break;" | 242 | " break;" | ||
242 | " }" | 243 | " }" | ||
243 | "}").arg(password)); | 244 | "}").arg(password)); | ||
244 | } | 245 | } | ||
245 | } else if (isTokenPage(url)) { | | |||
246 | /* Access token here - hide browser and tell user to wait until we | | |||
247 | * finish the authentication process ourselves */ | | |||
248 | sslIndicator->setVisible(false); | | |||
249 | urlEdit->setVisible(false); | | |||
250 | webview->setVisible(false); | | |||
251 | progressbar->setVisible(false); | | |||
252 | label->setVisible(true); | | |||
253 | | ||||
254 | setProgress(AuthWidget::TokensRetrieval); | | |||
255 | } | 246 | } | ||
256 | } | 247 | } | ||
257 | 248 | | |||
258 | void AuthWidgetPrivate::webviewFinished(bool ok) | 249 | void AuthWidgetPrivate::socketError(QAbstractSocket::SocketError socketError) | ||
259 | { | 250 | { | ||
260 | if (!ok) { | 251 | if (connection) | ||
261 | qCWarning(KGAPIDebug) << "Failed to load" << webview->url(); | 252 | connection->deleteLater(); | ||
mlaurent: const QByteArray ? | |||||
253 | qCDebug(KGAPIDebug) << QStringLiteral("Socket error when recieving response: %1").arg(socketError); | ||||
254 | emitError(InvalidResponse, QStringLiteral("Error recieving response: %1").arg(socketError)); | ||||
262 | } | 255 | } | ||
mlaurent: new line after '()' | |||||
263 | 256 | | |||
264 | const QUrl url = webview->url(); | 257 | void AuthWidgetPrivate::socketReady() | ||
265 | urlEdit->setText(url.toDisplayString(QUrl::PrettyDecoded)); | 258 | { | ||
266 | urlEdit->setCursorPosition(0); | 259 | Q_ASSERT(connection); | ||
267 | qCDebug(KGAPIDebug) << "URLFinished:" << url; | 260 | const QByteArray data = connection->readLine(); | ||
261 | connection->deleteLater(); | ||||
262 | qCDebug(KGAPIDebug) << QStringLiteral("Got connection on socket"); | ||||
263 | webview->stop(); | ||||
268 | 264 | | |||
269 | if (!isGoogleHost(url)) { | 265 | sslIndicator->setVisible(false); | ||
266 | urlEdit->setVisible(false); | ||||
mlaurent: it will crash if line is empty no or == 1 ? Perhaps you can test it no ? | |||||
I don't think it will crash. If line.size() is unequal 3, the remaining checks will be skipped (lazy evaluation). Those will only be checked, if line.size() == 3. davidk: I don't think it will crash. If line.size() is unequal 3, the remaining checks will be skipped… | |||||
dvratil: You are correct, I think Laurent just didn't notice the initial size check. | |||||
267 | webview->setVisible(false); | ||||
Please add qCDebug(KGAPIRaw) that logs the content of the received data for easier debugging in case there's an error. dvratil: Please add `qCDebug(KGAPIRaw)` that logs the content of the received data for easier debugging… | |||||
I don't want to log the recieved data, as I don't want to log the recieved token. Another fast enough application may grab it and access your data. There is a commented log in line 277, one can enable to log it. davidk: I don't want to log the recieved data, as I don't want to log the recieved token. Another fast… | |||||
268 | progressbar->setVisible(false); | ||||
Please use tr() instead of QStringLiteral here, this is a user-facing message so it needs to be localized. dvratil: Please use `tr()` instead of `QStringLiteral` here, this is a user-facing message so it needs… | |||||
269 | label->setVisible(true); | ||||
270 | | ||||
271 | const auto line = data.split(' '); | ||||
272 | if (line.size() != 3 || line.at(0) != QByteArray("GET") || !line.at(2).startsWith(QByteArray("HTTP/1.1"))) { | ||||
273 | qCDebug(KGAPIDebug) << QStringLiteral("Token response invalid"); | ||||
274 | emitError(InvalidResponse, QStringLiteral("Token response invalid")); | ||||
mlaurent: QLAtin1Char(' ') + const QStringList | |||||
You can use QByteArray::split() and continue operating on QByteArray below and only convert the value on line.at(1) to QString when building the QUrl dvratil: You can use `QByteArray::split()` and continue operating on `QByteArray` below and only convert… | |||||
270 | return; | 275 | return; | ||
271 | } | 276 | } | ||
272 | 277 | | |||
273 | if (isTokenPage(url)) { | 278 | //qCDebug(KGAPIRaw) << "Recieving data on socket: " << data; | ||
274 | const auto token = url.queryItemValue(QStringLiteral("approvalCode")); | 279 | const QUrl url(QString::fromLatin1(line.at(1))); | ||
275 | if (!token.isEmpty()) { | 280 | const QUrlQuery query(url.query()); | ||
276 | qCDebug(KGAPIDebug) << "Got token: " << token; | 281 | const QString code = query.queryItemValue(QStringLiteral("code")); | ||
277 | auto fetch = new KGAPI2::NewTokensFetchJob(token, apiKey, secretKey); | 282 | if (code.isEmpty()) { | ||
278 | connect(fetch, &Job::finished, this, &AuthWidgetPrivate::tokensReceived); | 283 | const QString error = query.queryItemValue(QStringLiteral("error")); | ||
mlaurent: const | |||||
284 | if (!error.isEmpty()) { | ||||
285 | emitError(UnknownError, error); | ||||
286 | qCDebug(KGAPIDebug) << error; | ||||
279 | } else { | 287 | } else { | ||
280 | qCWarning(KGAPIDebug) << "Failed to parse token from URL, peaking into HTML..."; | 288 | qCDebug(KGAPIDebug) << QStringLiteral("Could not extract token from HTTP answer"); | ||
281 | webview->page()->runJavaScript( | 289 | emitError(InvalidResponse, QStringLiteral("Could not extract token from HTTP answer")); | ||
dvratil: `tr()` instead of `QStringLiteral` | |||||
282 | QStringLiteral("document.getElementById(\"code\").value;"), | 290 | } | ||
283 | [this](const QVariant &result) { | | |||
284 | const auto token = result.toString(); | | |||
285 | if (token.isEmpty()) { | | |||
286 | qCWarning(KGAPIDebug) << "Peaked into HTML, but cound not find token :("; | | |||
287 | webview->page()->toHtml([](const QString &html) { | | |||
288 | qCDebug(KGAPIDebug) << "Parsing token page failed"; | | |||
289 | qCDebug(KGAPIDebug) << html; | | |||
290 | }); | | |||
291 | emitError(AuthError, tr("Parsing token page failed.")); | | |||
292 | return; | 291 | return; | ||
293 | } | 292 | } | ||
294 | qCDebug(KGAPIDebug) << "Peaked into HTML and found token: " << token; | 293 | | ||
295 | auto fetch = new KGAPI2::NewTokensFetchJob(token, apiKey, secretKey); | 294 | Q_ASSERT(serverPort != -1); | ||
295 | auto fetch = new KGAPI2::NewTokensFetchJob(code, apiKey, secretKey, serverPort); | ||||
296 | connect(fetch, &Job::finished, this, &AuthWidgetPrivate::tokensReceived); | 296 | connect(fetch, &Job::finished, this, &AuthWidgetPrivate::tokensReceived); | ||
297 | }); | | |||
298 | } | | |||
299 | } else { | | |||
300 | //qCDebug(KGAPIDebug) << "Unhandled page:" << url.host() << ", " << url.path(); | | |||
301 | } | | |||
302 | } | 297 | } | ||
303 | 298 | | |||
304 | void AuthWidgetPrivate::tokensReceived(KGAPI2::Job* job) | 299 | void AuthWidgetPrivate::tokensReceived(KGAPI2::Job* job) | ||
305 | { | 300 | { | ||
306 | KGAPI2::NewTokensFetchJob *tokensFetchJob = qobject_cast<KGAPI2::NewTokensFetchJob*>(job); | 301 | KGAPI2::NewTokensFetchJob *tokensFetchJob = qobject_cast<KGAPI2::NewTokensFetchJob*>(job); | ||
307 | 302 | | |||
308 | account->setAccessToken(tokensFetchJob->accessToken()); | 303 | account->setAccessToken(tokensFetchJob->accessToken()); | ||
309 | account->setRefreshToken(tokensFetchJob->refreshToken()); | 304 | account->setRefreshToken(tokensFetchJob->refreshToken()); | ||
Show All 32 Lines |
const QByteArray ?