Merge lp:~mandel/ubuntu-system-settings/donot-query-on-error into lp:ubuntu-system-settings

Proposed by Manuel de la Peña on 2015-08-27
Status: Merged
Approved by: Ken VanDine on 2015-08-27
Approved revision: 1514
Merged at revision: 1518
Proposed branch: lp:~mandel/ubuntu-system-settings/donot-query-on-error
Merge into: lp:ubuntu-system-settings
Prerequisite: lp:~ken-vandine/ubuntu-system-settings/emit_credentials_deleted
Diff against target: 554 lines (+147/-117)
12 files modified
plugins/system-update/PageComponent.qml (+1/-2)
plugins/system-update/download_tracker.cpp (+1/-1)
plugins/system-update/network.cpp (+104/-66)
plugins/system-update/network.h (+12/-17)
plugins/system-update/plugin/CMakeLists.txt (+1/-1)
plugins/system-update/update.h (+1/-4)
plugins/system-update/update_manager.cpp (+10/-12)
plugins/system-update/update_manager.h (+4/-8)
tests/plugins/system-update/CMakeLists.txt (+1/-1)
tests/plugins/system-update/fakenetwork.cpp (+1/-2)
tests/plugins/system-update/fakenetwork.h (+10/-2)
tests/plugins/system-update/tst_network.cpp (+1/-1)
To merge this branch: bzr merge lp:~mandel/ubuntu-system-settings/donot-query-on-error
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Needs Fixing on 2015-08-27
Ken VanDine 2015-08-27 Approve on 2015-08-27
Review via email: mp+269319@code.launchpad.net

Commit Message

Sign the query in order to get a possible auth error from the server and stop the user from trying to do updates with invalid creds.

Description of the Change

Sign the query in order to get a possible auth error from the server and stop the user from trying to do updates with invalid creds.

To post a comment you must log in.
1513. By Manuel de la Peña on 2015-08-27

Improve the ui used to show the lack of creds.

Ken VanDine (ken-vandine) wrote :

This looks great, one suggestion:

In PageComponent.qml, handle onCredentialsDeleted the same as onCredentialsNotFound. This will show the prompt to signin to U1 under the system update.

Ken VanDine (ken-vandine) wrote :

Perfect, thanks!

review: Approve
1514. By Manuel de la Peña on 2015-08-27

Move the network to its correct location.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/system-update/PageComponent.qml'
2--- plugins/system-update/PageComponent.qml 2015-06-29 13:06:41 +0000
3+++ plugins/system-update/PageComponent.qml 2015-08-27 10:19:03 +0000
4@@ -205,8 +205,7 @@
5 }
6
7 onCredentialsDeleted: {
8- credentialsNotification.visible = false;
9- uoaConfig.exec();
10+ credentialsNotification.visible = true;
11 }
12
13 onSystemUpdateDownloaded: {
14
15=== modified file 'plugins/system-update/download_tracker.cpp'
16--- plugins/system-update/download_tracker.cpp 2015-02-26 18:59:51 +0000
17+++ plugins/system-update/download_tracker.cpp 2015-08-27 10:19:03 +0000
18@@ -23,7 +23,7 @@
19 #include <ubuntu/download_manager/error.h>
20
21 #include "download_tracker.h"
22-#include "network/network.h"
23+#include "network.h"
24
25 namespace {
26 const QString DOWNLOAD_COMMAND = "post-download-command";
27
28=== removed directory 'plugins/system-update/network'
29=== renamed file 'plugins/system-update/network/network.cpp' => 'plugins/system-update/network.cpp'
30--- plugins/system-update/network/network.cpp 2015-08-27 10:19:03 +0000
31+++ plugins/system-update/network.cpp 2015-08-27 10:19:03 +0000
32@@ -29,7 +29,6 @@
33
34 namespace {
35 const QString URL_APPS = "https://search.apps.ubuntu.com/api/v1/click-metadata";
36- const QString APPS_DATA = "APPS_DATA";
37 constexpr static const char* FRAMEWORKS_FOLDER {"/usr/share/click/frameworks/"};
38 constexpr static const char* FRAMEWORKS_PATTERN {"*.framework"};
39 constexpr static const int FRAMEWORKS_EXTENSION_LENGTH = 10; // strlen(".framework")
40@@ -58,6 +57,49 @@
41 return result;
42 }
43
44+bool Network::replyIsValid(QNetworkReply *reply)
45+{
46+ auto statusAttr = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
47+ if (!statusAttr.isValid()) {
48+ Q_EMIT errorOccurred();
49+ return false;
50+ }
51+
52+ int httpStatus = statusAttr.toInt();
53+ qWarning() << "HTTP Status: " << httpStatus;
54+
55+ if (httpStatus == 401 || httpStatus == 403) {
56+ qWarning() << "Emitting credetials error.";
57+ Q_EMIT credentialError();
58+ return false;
59+ }
60+
61+ return true;
62+}
63+
64+void Network::onTokenRequestFinished(Update* app, QNetworkReply* r)
65+{
66+ // the scoped pointer will take care of calling the deleteLater when leaving the slot
67+ QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(r);
68+
69+ // check if the reply is valid, this method will emit all the required signals to propagate errors to the rest
70+ // of the plugin
71+ if (!replyIsValid(r)) {
72+ qWarning() << "Reply is not valid.";
73+ return;
74+ }
75+
76+ if (reply->hasRawHeader(X_CLICK_TOKEN)) {
77+ if (app != nullptr) {
78+ QString header(reply->rawHeader(X_CLICK_TOKEN));
79+ Q_EMIT clickTokenObtained(app, header);
80+ }
81+ return;
82+ }
83+
84+ Q_EMIT errorOccurred();
85+}
86+
87 std::string Network::architectureFromDpkg()
88 {
89 QString program("dpkg");
90@@ -91,6 +133,7 @@
91
92 void Network::checkForNewVersions(QHash<QString, Update*> &apps)
93 {
94+ qWarning() << __PRETTY_FUNCTION__;
95 m_apps = apps;
96 QJsonObject serializer;
97 QJsonArray array;
98@@ -107,18 +150,19 @@
99 QByteArray content = doc.toJson();
100
101 QString urlApps = getUrlApps();
102+ QString authHeader = m_token.signUrl(urlApps, QStringLiteral("POST"), true);
103+ QUrl url(urlApps);
104+ url.setQuery(authHeader);
105+
106 QNetworkRequest request;
107 request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
108 request.setRawHeader(QByteArray("X-Ubuntu-Frameworks"), QByteArray::fromStdString(frameworks.str()));
109 request.setRawHeader(QByteArray("X-Ubuntu-Architecture"), QByteArray::fromStdString(getArchitecture()));
110- request.setUrl(QUrl(urlApps));
111-
112- RequestObject* reqObject = new RequestObject(QString(APPS_DATA));
113- request.setOriginatingObject(reqObject);
114+ request.setUrl(url);
115
116 auto reply = m_nam.post(request, content);
117
118- connect(reply, &QNetworkReply::finished, this, &Network::onReplyFinished);
119+ connect(reply, &QNetworkReply::finished, this, &Network::onUpdatesCheckFinished);
120 connect(reply, &QNetworkReply::sslErrors, this, &Network::onReplySslErrors);
121 connect(reply, static_cast<void(QNetworkReply::*)
122 (QNetworkReply::NetworkError)>(&QNetworkReply::error),
123@@ -139,66 +183,49 @@
124 return command;
125 }
126
127-void Network::onReplyFinished()
128+void Network::onUpdatesCheckFinished()
129 {
130 // the scoped pointer will take care of calling the deleteLater when leaving the slot
131- QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(qobject_cast<QNetworkReply*>(sender()));
132- auto statusAttr = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
133- if (!statusAttr.isValid()) {
134- Q_EMIT errorOccurred();
135- return;
136- }
137-
138- int httpStatus = statusAttr.toInt();
139-
140- if (httpStatus == 401 || httpStatus == 403) {
141- Q_EMIT credentialError();
142- return;
143- }
144-
145- if (httpStatus == 200 || httpStatus == 201) {
146- if (reply->hasRawHeader(X_CLICK_TOKEN)) {
147- auto app = qobject_cast<Update*>(reply->request().originatingObject());
148- if (app != nullptr) {
149- QString header(reply->rawHeader(X_CLICK_TOKEN));
150- Q_EMIT clickTokenObtained(app, header);
151- }
152- return;
153- }
154-
155- QByteArray payload = reply->readAll();
156- QJsonDocument document = QJsonDocument::fromJson(payload);
157-
158- auto state = qobject_cast<RequestObject*>(reply->request().originatingObject());
159- if (state != nullptr && state->operation.contains(APPS_DATA) && document.isArray()) {
160- QJsonArray array = document.array();
161- bool updates = false;
162- for (int i = 0; i < array.size(); i++) {
163- auto object = array.at(i).toObject();
164- auto name = object["name"].toString();
165- auto version = object["version"].toString();
166- auto icon_url = object["icon_url"].toString();
167- auto url = object["download_url"].toString();
168- auto download_sha512 = object["download_sha512"].toString();
169- auto size = object["binary_filesize"].toInt();
170- if (m_apps.contains(name)) {
171- m_apps[name]->setRemoteVersion(version);
172- if (m_apps[name]->updateRequired()) {
173- m_apps[name]->setIconUrl(icon_url);
174- m_apps[name]->setDownloadUrl(url);
175- m_apps[name]->setBinaryFilesize(size);
176- m_apps[name]->setDownloadSha512(download_sha512);
177- updates = true;
178- }
179+ auto r = qobject_cast<QNetworkReply*>(sender());
180+
181+ // check for http error status and emit all the required signals
182+ if (!replyIsValid(r)) {
183+ qWarning() << "Reply is not valid.";
184+ return;
185+ }
186+
187+ QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(r);
188+
189+ auto document = QJsonDocument::fromJson(reply->readAll());
190+
191+ if (document.isArray()) {
192+ QJsonArray array = document.array();
193+ bool updates = false;
194+ for (int i = 0; i < array.size(); i++) {
195+ auto object = array.at(i).toObject();
196+ auto name = object["name"].toString();
197+ auto version = object["version"].toString();
198+ auto icon_url = object["icon_url"].toString();
199+ auto url = object["download_url"].toString();
200+ auto download_sha512 = object["download_sha512"].toString();
201+ auto size = object["binary_filesize"].toInt();
202+ if (m_apps.contains(name)) {
203+ m_apps[name]->setRemoteVersion(version);
204+ if (m_apps[name]->updateRequired()) {
205+ m_apps[name]->setIconUrl(icon_url);
206+ m_apps[name]->setDownloadUrl(url);
207+ m_apps[name]->setBinaryFilesize(size);
208+ m_apps[name]->setDownloadSha512(download_sha512);
209+ updates = true;
210 }
211 }
212- if (updates) {
213- Q_EMIT updatesFound();
214- return;
215- } else {
216- Q_EMIT updatesNotFound();
217- return;
218- }
219+ }
220+ if (updates) {
221+ Q_EMIT updatesFound();
222+ return;
223+ } else {
224+ Q_EMIT updatesNotFound();
225+ return;
226 }
227 }
228
229@@ -229,20 +256,31 @@
230 reply->deleteLater();
231 }
232
233-void Network::getClickToken(Update *app, const QString &url,
234- const QString &authHeader)
235+void Network::getClickToken(Update *app, const QString &url)
236 {
237+ qWarning() << __PRETTY_FUNCTION__;
238+ if (!m_token.isValid()) {
239+ app->setError("Invalid User Token");
240+ return;
241+ }
242+
243+ QString authHeader = m_token.signUrl(app->downloadUrl(), QStringLiteral("HEAD"), true);
244+ app->setClickUrl(app->downloadUrl());
245+
246 QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
247 QString signUrl = environment.value("CLICK_TOKEN_URL", url);
248 QUrl query(signUrl);
249 query.setQuery(authHeader);
250 QNetworkRequest request;
251 request.setUrl(query);
252- request.setOriginatingObject(app);
253
254 auto reply = m_nam.head(request);
255
256- connect(reply, &QNetworkReply::finished, this, &Network::onReplyFinished);
257+ connect(reply, &QNetworkReply::finished, this, [=](){
258+ auto reply = qobject_cast<QNetworkReply*>(sender());
259+ onTokenRequestFinished(app, reply);
260+ });
261+
262 connect(reply, &QNetworkReply::sslErrors, this, &Network::onReplySslErrors);
263 connect(reply, static_cast<void(QNetworkReply::*)
264 (QNetworkReply::NetworkError)>(&QNetworkReply::error),
265
266=== renamed file 'plugins/system-update/network/network.h' => 'plugins/system-update/network.h'
267--- plugins/system-update/network/network.h 2015-08-27 10:19:03 +0000
268+++ plugins/system-update/network.h 2015-08-27 10:19:03 +0000
269@@ -19,29 +19,18 @@
270 #ifndef NETWORK_H
271 #define NETWORK_H
272
273+#include <token.h>
274 #include <QObject>
275 #include <QtNetwork/QNetworkAccessManager>
276 #include <QtNetwork/QNetworkReply>
277 #include <QHash>
278-#include "../update.h"
279+
280+#include "update.h"
281
282 #define X_CLICK_TOKEN "X-Click-Token"
283
284 namespace UpdatePlugin {
285
286-class RequestObject : public QObject
287-{
288- Q_OBJECT
289-public:
290- explicit RequestObject(QString oper, QObject *parent = 0) :
291- QObject(parent)
292- {
293- operation = oper;
294- }
295-
296- QString operation;
297-};
298-
299 class Network : public QObject
300 {
301 Q_OBJECT
302@@ -49,11 +38,14 @@
303 explicit Network(QObject *parent = 0);
304
305 void checkForNewVersions(QHash<QString, Update*> &apps);
306- void getClickToken(Update *app, const QString &url,
307- const QString &authHeader);
308+ void getClickToken(Update *app, const QString &url);
309+
310 virtual std::vector<std::string> getAvailableFrameworks();
311 virtual std::string getArchitecture();
312
313+ void setUbuntuOneToken(UbuntuOne::Token token) { m_token = token; }
314+ UbuntuOne::Token getUbuntuOneToken() { return m_token; }
315+
316 Q_SIGNALS:
317 void updatesFound();
318 void updatesNotFound();
319@@ -64,16 +56,19 @@
320 void credentialError();
321
322 private Q_SLOTS:
323- void onReplyFinished();
324+ void onUpdatesCheckFinished();
325 void onReplySslErrors(const QList<QSslError> & errors);
326 void onReplyError(QNetworkReply::NetworkError code);
327
328 private:
329 QNetworkAccessManager m_nam;
330 QHash<QString, Update*> m_apps;
331+ UbuntuOne::Token m_token;
332
333 QString getUrlApps();
334 QString getFrameworksDir();
335+ bool replyIsValid(QNetworkReply *reply);
336+ void onTokenRequestFinished(Update* update, QNetworkReply* reply);
337
338 protected:
339 virtual std::string architectureFromDpkg();
340
341=== modified file 'plugins/system-update/plugin/CMakeLists.txt'
342--- plugins/system-update/plugin/CMakeLists.txt 2014-10-22 19:37:42 +0000
343+++ plugins/system-update/plugin/CMakeLists.txt 2015-08-27 10:19:03 +0000
344@@ -1,7 +1,7 @@
345 SET (CMAKE_AUTOMOC ON)
346 include_directories(${CMAKE_CURRENT_BINARY_DIR})
347
348-add_library(update-plugin SHARED update-plugin.h update-plugin.cpp ../network/network.cpp ../network/network.h
349+add_library(update-plugin SHARED update-plugin.h update-plugin.cpp ../network.cpp ../network.h
350 ../update.cpp ../update.h ../update_manager.cpp ../update_manager.h ../system_update.cpp ../system_update.h
351 ../download_tracker.h ../download_tracker.cpp)
352
353
354=== modified file 'plugins/system-update/update.h'
355--- plugins/system-update/update.h 2014-10-07 17:54:46 +0000
356+++ plugins/system-update/update.h 2015-08-27 10:19:03 +0000
357@@ -18,8 +18,7 @@
358 *
359 */
360
361-#ifndef UPDATE_H
362-#define UPDATE_H
363+#pragma once
364
365 #include <QObject>
366 #include <QtQml>
367@@ -144,5 +143,3 @@
368 };
369
370 }
371-
372-#endif // UPDATE_H
373
374=== modified file 'plugins/system-update/update_manager.cpp'
375--- plugins/system-update/update_manager.cpp 2015-08-27 10:19:03 +0000
376+++ plugins/system-update/update_manager.cpp 2015-08-27 10:19:03 +0000
377@@ -18,15 +18,19 @@
378 *
379 */
380
381-#include "update_manager.h"
382-#include <QString>
383-#include <QStringList>
384+
385+#include <QDBusInterface>
386 #include <QJsonDocument>
387 #include <QJsonObject>
388 #include <QJsonArray>
389 #include <QJsonValue>
390 #include <QProcessEnvironment>
391-#include <QDBusInterface>
392+#include <QString>
393+#include <QStringList>
394+#include <ssoservice.h>
395+
396+#include "update_manager.h"
397+#include "network.h"
398
399 using namespace UbuntuOne;
400
401@@ -164,7 +168,7 @@
402
403 void UpdateManager::handleCredentialsFound(Token token)
404 {
405- m_token = token;
406+ m_network.setUbuntuOneToken(token);
407 QStringList args("list");
408 args << "--manifest";
409 QString command = getClickCommand();
410@@ -332,13 +336,7 @@
411
412 void UpdateManager::downloadApp(Update *app)
413 {
414- if (m_token.isValid()) {
415- QString authHeader = m_token.signUrl(app->downloadUrl(), QStringLiteral("HEAD"), true);
416- app->setClickUrl(app->downloadUrl());
417- m_network.getClickToken(app, app->downloadUrl(), authHeader);
418- } else {
419- app->setError("Invalid User Token");
420- }
421+ m_network.getClickToken(app, app->downloadUrl());
422 }
423
424 void UpdateManager::clickTokenReceived(Update *app, const QString &clickToken)
425
426=== modified file 'plugins/system-update/update_manager.h'
427--- plugins/system-update/update_manager.h 2015-08-27 10:19:03 +0000
428+++ plugins/system-update/update_manager.h 2015-08-27 10:19:03 +0000
429@@ -18,8 +18,7 @@
430 *
431 */
432
433-#ifndef UPDATEMANAGER_H
434-#define UPDATEMANAGER_H
435+#pragma once
436
437 #include <QObject>
438 #include <QtQml>
439@@ -40,7 +39,7 @@
440 #else
441 #include <ssoservice.h>
442 #include <QProcess>
443-#include "network/network.h"
444+#include "network.h"
445 #include "system_update.h"
446 #endif
447
448@@ -112,8 +111,8 @@
449 QHash<QString, Update*> get_apps() { return m_apps; }
450 QVariantList get_model() { return m_model; }
451 int get_downloadMode() { return m_downloadMode; }
452- void set_token(Token& t) { m_token = t; }
453- Token get_token() { return m_token; }
454+ void set_token(Token& t) { m_network.setUbuntuOneToken(t); }
455+ Token get_token() { return m_network.getUbuntuOneToken(); }
456 void setCheckintUpdates(int value) { m_checkingUpdates = value; }
457 void setCheckSystemUpdates(int value) { m_systemCheckingUpdate = value; }
458 void setCheckClickUpdates(int value) { m_clickCheckingUpdate = value; }
459@@ -149,7 +148,6 @@
460 QHash<QString, Update*> m_apps;
461 int m_downloadMode;
462 QVariantList m_model;
463- Token m_token;
464 QString m_latestDownload;
465
466 #ifdef TESTS
467@@ -174,5 +172,3 @@
468 };
469
470 }
471-
472-#endif // UPDATEMANAGER_H
473
474=== modified file 'tests/plugins/system-update/CMakeLists.txt'
475--- tests/plugins/system-update/CMakeLists.txt 2015-04-30 19:35:35 +0000
476+++ tests/plugins/system-update/CMakeLists.txt 2015-08-27 10:19:03 +0000
477@@ -28,7 +28,7 @@
478 add_executable(tst-network
479 tst_network.cpp
480 ../../../plugins/system-update/update.cpp
481- ../../../plugins/system-update/network/network.cpp
482+ ../../../plugins/system-update/network.cpp
483 )
484
485 # set the path to the library folder
486
487=== modified file 'tests/plugins/system-update/fakenetwork.cpp'
488--- tests/plugins/system-update/fakenetwork.cpp 2014-02-26 11:26:01 +0000
489+++ tests/plugins/system-update/fakenetwork.cpp 2015-08-27 10:19:03 +0000
490@@ -40,10 +40,9 @@
491 emit this->downloadUrlFound(packagename, "http://canonical.com");
492 }
493
494-void FakeNetwork::getClickToken(Update* app, const QString& url, const QString& authHeader)
495+void FakeNetwork::getClickToken(Update* app, const QString& url)
496 {
497 Q_UNUSED(url);
498- Q_UNUSED(authHeader);
499 QString fakeHeader("x-click-token-header");
500 emit this->clickTokenObtained(app, fakeHeader);
501 }
502
503=== modified file 'tests/plugins/system-update/fakenetwork.h'
504--- tests/plugins/system-update/fakenetwork.h 2015-08-27 10:19:03 +0000
505+++ tests/plugins/system-update/fakenetwork.h 2015-08-27 10:19:03 +0000
506@@ -19,9 +19,12 @@
507 #ifndef FAKENETWORK_H
508 #define FAKENETWORK_H
509
510+#include <token.h>
511+
512 #include <QObject>
513 #include <QHash>
514 #include <QString>
515+
516 #include "update.h"
517
518 namespace UpdatePlugin {
519@@ -34,8 +37,10 @@
520
521 void checkForNewVersions(QHash<QString, Update*> &apps);
522 void getResourceUrl(const QString& packagename);
523- void getClickToken(Update* app, const QString& url, const QString& authHeader);
524-
525+ void getClickToken(Update* app, const QString& url);
526+ void setUbuntuOneToken(UbuntuOne::Token t) { m_token = t; }
527+ UbuntuOne::Token getUbuntuOneToken() { return m_token; }
528+
529 signals:
530 void updatesFound();
531 void updatesNotFound();
532@@ -45,6 +50,9 @@
533 void credentialError();
534 void downloadUrlFound(const QString& packagename, const QString& url);
535 void clickTokenObtained(Update* app, const QString& clickToken);
536+
537+private:
538+ UbuntuOne::Token m_token;
539 };
540
541 }
542
543=== modified file 'tests/plugins/system-update/tst_network.cpp'
544--- tests/plugins/system-update/tst_network.cpp 2015-04-30 14:16:22 +0000
545+++ tests/plugins/system-update/tst_network.cpp 2015-08-27 10:19:03 +0000
546@@ -22,7 +22,7 @@
547 #include <QObject>
548 #include <QTest>
549 #include <QString>
550-#include "network/network.h"
551+#include "network.h"
552 #include "update.h"
553
554 using namespace UpdatePlugin;

Subscribers

People subscribed via source and target branches