Merge lp:~mandel/ubuntu-system-settings/correct-nm-usage into lp:ubuntu-system-settings

Proposed by Manuel de la Peña on 2015-08-20
Status: Merged
Approved by: Ken VanDine on 2015-08-26
Approved revision: 1507
Merged at revision: 1516
Proposed branch: lp:~mandel/ubuntu-system-settings/correct-nm-usage
Merge into: lp:ubuntu-system-settings
Diff against target: 218 lines (+94/-64)
2 files modified
plugins/system-update/network/network.cpp (+91/-63)
plugins/system-update/network/network.h (+3/-1)
To merge this branch: bzr merge lp:~mandel/ubuntu-system-settings/correct-nm-usage
Reviewer Review Type Date Requested Status
Ken VanDine 2015-08-20 Approve on 2015-08-26
PS Jenkins bot continuous-integration Needs Fixing on 2015-08-20
Review via email: mp+268582@code.launchpad.net

Commit Message

The updates page is leaking objects when we have a successful update and when we do have errors. The following branch ensures that no memory is wasted.

Description of the Change

The updates page is leaking objects when we have a successful update and when we do have errors. The following branch ensures that no memory is wasted.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'plugins/system-update/network/network.cpp'
2--- plugins/system-update/network/network.cpp 2015-04-30 19:35:35 +0000
3+++ plugins/system-update/network/network.cpp 2015-08-20 10:28:19 +0000
4@@ -25,6 +25,7 @@
5 #include <QByteArray>
6 #include <QUrl>
7 #include <QProcessEnvironment>
8+#include <QScopedPointer>
9
10 namespace {
11 const QString URL_APPS = "https://search.apps.ubuntu.com/api/v1/click-metadata";
12@@ -40,8 +41,6 @@
13 QObject(parent),
14 m_nam(this)
15 {
16- QObject::connect(&m_nam, SIGNAL(finished(QNetworkReply*)),
17- this, SLOT(onReply(QNetworkReply*)));
18 }
19
20 std::string Network::getArchitecture()
21@@ -113,9 +112,17 @@
22 request.setRawHeader(QByteArray("X-Ubuntu-Frameworks"), QByteArray::fromStdString(frameworks.str()));
23 request.setRawHeader(QByteArray("X-Ubuntu-Architecture"), QByteArray::fromStdString(getArchitecture()));
24 request.setUrl(QUrl(urlApps));
25+
26 RequestObject* reqObject = new RequestObject(QString(APPS_DATA));
27 request.setOriginatingObject(reqObject);
28- m_nam.post(request, content);
29+
30+ auto reply = m_nam.post(request, content);
31+
32+ connect(reply, &QNetworkReply::finished, this, &Network::onReplyFinished);
33+ connect(reply, &QNetworkReply::sslErrors, this, &Network::onReplySslErrors);
34+ connect(reply, static_cast<void(QNetworkReply::*)
35+ (QNetworkReply::NetworkError)>(&QNetworkReply::error),
36+ this, &Network::onReplyError);
37 }
38
39 QString Network::getUrlApps()
40@@ -132,74 +139,88 @@
41 return command;
42 }
43
44-void Network::onReply(QNetworkReply *reply)
45+void Network::onReplyFinished()
46 {
47- if (reply->error() == QNetworkReply::NoError) {
48- QVariant statusAttr = reply->attribute(
49- QNetworkRequest::HttpStatusCodeAttribute);
50- if (!statusAttr.isValid()) {
51- Q_EMIT errorOccurred();
52+ // the scoped pointer will take care of calling the deleteLater when leaving the slot
53+ QScopedPointer<QNetworkReply, QScopedPointerDeleteLater> reply(qobject_cast<QNetworkReply*>(sender()));
54+ auto statusAttr = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
55+ if (!statusAttr.isValid()) {
56+ Q_EMIT errorOccurred();
57+ return;
58+ }
59+
60+ int httpStatus = statusAttr.toInt();
61+
62+ if (httpStatus == 200 || httpStatus == 201) {
63+ if (reply->hasRawHeader(X_CLICK_TOKEN)) {
64+ auto app = qobject_cast<Update*>(reply->request().originatingObject());
65+ if (app != nullptr) {
66+ QString header(reply->rawHeader(X_CLICK_TOKEN));
67+ Q_EMIT clickTokenObtained(app, header);
68+ }
69 return;
70 }
71
72- int httpStatus = statusAttr.toInt();
73-
74- if (httpStatus == 200 || httpStatus == 201) {
75- if (reply->hasRawHeader(X_CLICK_TOKEN)) {
76- Update* app = qobject_cast<Update*>(
77- reply->request().originatingObject());
78- if (app != nullptr) {
79- QString header(reply->rawHeader(X_CLICK_TOKEN));
80- Q_EMIT clickTokenObtained(app, header);
81- }
82- reply->deleteLater();
83- return;
84- }
85-
86- QByteArray payload = reply->readAll();
87- QJsonDocument document = QJsonDocument::fromJson(payload);
88-
89- RequestObject* state = qobject_cast<RequestObject*>(reply->request().originatingObject());
90- if (state != nullptr && state->operation.contains(APPS_DATA) && document.isArray()) {
91- QJsonArray array = document.array();
92- bool updates = false;
93- for (int i = 0; i < array.size(); i++) {
94- QJsonObject object = array.at(i).toObject();
95- QString name = object.value("name").toString();
96- QString version = object.value("version").toString();
97- QString icon_url = object.value("icon_url").toString();
98- QString url = object.value("download_url").toString();
99- QString download_sha512 = object.value("download_sha512").toString();
100- int size = object.value("binary_filesize").toVariant().toInt();
101- if (m_apps.contains(name)) {
102- m_apps[name]->setRemoteVersion(version);
103- if (m_apps[name]->updateRequired()) {
104- m_apps[name]->setIconUrl(icon_url);
105- m_apps[name]->setDownloadUrl(url);
106- m_apps[name]->setBinaryFilesize(size);
107- m_apps[name]->setDownloadSha512(download_sha512);
108- updates = true;
109- }
110+ QByteArray payload = reply->readAll();
111+ QJsonDocument document = QJsonDocument::fromJson(payload);
112+
113+ auto state = qobject_cast<RequestObject*>(reply->request().originatingObject());
114+ if (state != nullptr && state->operation.contains(APPS_DATA) && document.isArray()) {
115+ QJsonArray array = document.array();
116+ bool updates = false;
117+ for (int i = 0; i < array.size(); i++) {
118+ auto object = array.at(i).toObject();
119+ auto name = object["name"].toString();
120+ auto version = object["version"].toString();
121+ auto icon_url = object["icon_url"].toString();
122+ auto url = object["download_url"].toString();
123+ auto download_sha512 = object["download_sha512"].toString();
124+ auto size = object["binary_filesize"].toInt();
125+ if (m_apps.contains(name)) {
126+ m_apps[name]->setRemoteVersion(version);
127+ if (m_apps[name]->updateRequired()) {
128+ m_apps[name]->setIconUrl(icon_url);
129+ m_apps[name]->setDownloadUrl(url);
130+ m_apps[name]->setBinaryFilesize(size);
131+ m_apps[name]->setDownloadSha512(download_sha512);
132+ updates = true;
133 }
134 }
135- if (updates) {
136- Q_EMIT updatesFound();
137- } else {
138- Q_EMIT updatesNotFound();
139- }
140+ }
141+ if (updates) {
142+ Q_EMIT updatesFound();
143+ return;
144 } else {
145- Q_EMIT errorOccurred();
146+ Q_EMIT updatesNotFound();
147+ return;
148 }
149- } else {
150- Q_EMIT errorOccurred();
151 }
152- } else if (reply->error() == QNetworkReply::TemporaryNetworkFailureError ||
153- reply->error() == QNetworkReply::UnknownNetworkError) {
154- Q_EMIT networkError();
155- } else {
156- Q_EMIT serverError();
157- }
158-
159+ }
160+
161+ Q_EMIT errorOccurred();
162+}
163+
164+void Network::onReplySslErrors(const QList<QSslError>&)
165+{
166+ auto reply = sender();
167+ // Should this be a server or a network error??
168+ Q_EMIT serverError();
169+ reply->deleteLater();
170+}
171+
172+void Network::onReplyError(QNetworkReply::NetworkError code)
173+{
174+ auto reply = sender();
175+ switch (code) {
176+ case QNetworkReply::TemporaryNetworkFailureError:
177+ case QNetworkReply::UnknownNetworkError:
178+ case QNetworkReply::UnknownProxyError:
179+ case QNetworkReply::UnknownServerError:
180+ Q_EMIT networkError();
181+ break;
182+ default:
183+ Q_EMIT serverError();
184+ }
185 reply->deleteLater();
186 }
187
188@@ -213,7 +234,14 @@
189 QNetworkRequest request;
190 request.setUrl(query);
191 request.setOriginatingObject(app);
192- m_nam.head(request);
193+
194+ auto reply = m_nam.head(request);
195+
196+ connect(reply, &QNetworkReply::finished, this, &Network::onReplyFinished);
197+ connect(reply, &QNetworkReply::sslErrors, this, &Network::onReplySslErrors);
198+ connect(reply, static_cast<void(QNetworkReply::*)
199+ (QNetworkReply::NetworkError)>(&QNetworkReply::error),
200+ this, &Network::onReplyError);
201 }
202
203 }
204
205=== modified file 'plugins/system-update/network/network.h'
206--- plugins/system-update/network/network.h 2015-04-30 19:35:35 +0000
207+++ plugins/system-update/network/network.h 2015-08-20 10:28:19 +0000
208@@ -63,7 +63,9 @@
209 void clickTokenObtained(Update *app, const QString &clickToken);
210
211 private Q_SLOTS:
212- void onReply(QNetworkReply*);
213+ void onReplyFinished();
214+ void onReplySslErrors(const QList<QSslError> & errors);
215+ void onReplyError(QNetworkReply::NetworkError code);
216
217 private:
218 QNetworkAccessManager m_nam;

Subscribers

People subscribed via source and target branches