Merge lp:~unity-api-team/unity-scope-click/sign-all-the-things into lp:unity-scope-click
- sign-all-the-things
- Merge into trunk
Proposed by
dobey
Status: | Superseded |
---|---|
Proposed branch: | lp:~unity-api-team/unity-scope-click/sign-all-the-things |
Merge into: | lp:unity-scope-click |
Diff against target: |
2403 lines (+517/-1182) 22 files modified
CMakeLists.txt (+1/-1) libclickscope/click/download-manager.cpp (+97/-323) libclickscope/click/download-manager.h (+20/-50) libclickscope/click/preview.cpp (+93/-83) libclickscope/click/preview.h (+11/-11) libclickscope/click/webclient.cpp (+17/-4) libclickscope/click/webclient.h (+2/-1) libclickscope/tests/mock_ubuntu_download_manager.h (+14/-1) libclickscope/tests/mock_webclient.h (+3/-2) libclickscope/tests/test_download_manager.cpp (+174/-439) libclickscope/tests/test_index.cpp (+13/-1) libclickscope/tests/test_preview.cpp (+38/-60) libclickscope/tests/test_reviews.cpp (+13/-0) libclickscope/tests/test_webclient.cpp (+4/-4) scope/clickapps/apps-scope.cpp (+7/-4) scope/clickapps/apps-scope.h (+3/-0) scope/clickstore/store-scope.cpp (+4/-1) scope/clickstore/store-scope.h (+3/-0) scope/tests/CMakeLists.txt (+0/-1) scope/tests/download_manager_tool/CMakeLists.txt (+0/-14) scope/tests/download_manager_tool/download_manager_tool.cpp (+0/-123) scope/tests/download_manager_tool/download_manager_tool.h (+0/-59) |
To merge this branch: | bzr merge lp:~unity-api-team/unity-scope-click/sign-all-the-things |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Unity API Team | Pending | ||
Review via email: mp+287672@code.launchpad.net |
Commit message
Fix the signing of store webservice urls
Description of the change
To post a comment you must log in.
- 441. By dobey
-
Link bug report.
- 442. By dobey
-
More cleanup of usage of the credentials service.
- 443. By dobey
-
Use a cached token.
- 444. By dobey
-
Better signal/error handling.
- 445. By dobey
-
Try to keep qt event loop from being blocked by std::future.
- 446. By dobey
-
Continue forwarding the found signal.
- 447. By Antti Kaijanmäki
-
initialize std::future_status
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2016-02-04 15:24:05 +0000 |
3 | +++ CMakeLists.txt 2016-03-01 16:46:59 +0000 |
4 | @@ -60,7 +60,7 @@ |
5 | |
6 | include(EnableCoverageReport) |
7 | ENABLE_COVERAGE_REPORT(TARGETS ${SCOPE_LIB_NAME} ${STORE_LIB_UNVERSIONED} ${APPS_LIB_UNVERSIONED} |
8 | - TESTS click_scope_integration_tests libclick-scope-tests fake_launcher click-scope-tests apps-scope-tests download_manager_tool click_interface_tool init-departments test-integration-harness |
9 | + TESTS click_scope_integration_tests libclick-scope-tests fake_launcher click-scope-tests apps-scope-tests click_interface_tool init-departments |
10 | FILTER /usr/include ${CMAKE_BINARY_DIR}/* |
11 | ) |
12 | |
13 | |
14 | === modified file 'libclickscope/click/download-manager.cpp' |
15 | --- libclickscope/click/download-manager.cpp 2014-09-24 19:42:19 +0000 |
16 | +++ libclickscope/click/download-manager.cpp 2016-03-01 16:46:59 +0000 |
17 | @@ -1,5 +1,5 @@ |
18 | /* |
19 | - * Copyright (C) 2014 Canonical Ltd. |
20 | + * Copyright (C) 2014-2016 Canonical Ltd. |
21 | * |
22 | * This program is free software: you can redistribute it and/or modify it |
23 | * under the terms of the GNU General Public License version 3, as published |
24 | @@ -47,7 +47,7 @@ |
25 | #include <ubuntu/download_manager/download.h> |
26 | #include <ubuntu/download_manager/error.h> |
27 | |
28 | -namespace |
29 | +namespace click |
30 | { |
31 | |
32 | static const QString DOWNLOAD_APP_ID_KEY = "app_id"; |
33 | @@ -56,269 +56,30 @@ |
34 | static const QString DOWNLOAD_COMMAND = CLICK_INSTALL_HELPER; |
35 | |
36 | static const QString DOWNLOAD_MANAGER_SHA512 = "sha512"; |
37 | -} |
38 | - |
39 | -struct click::DownloadManager::Private |
40 | -{ |
41 | - Private(const QSharedPointer<click::network::AccessManager>& networkAccessManager, |
42 | - const QSharedPointer<click::CredentialsService>& credentialsService, |
43 | - const QSharedPointer<udm::Manager>& systemDownloadManager) |
44 | - : nam(networkAccessManager), credentialsService(credentialsService), |
45 | - systemDownloadManager(systemDownloadManager) |
46 | - { |
47 | - } |
48 | - |
49 | - void updateCredentialsFromService() |
50 | - { |
51 | - credentialsService->getCredentials(); |
52 | - } |
53 | - |
54 | - void invalidateCredentialsFromService() |
55 | - { |
56 | - credentialsService->invalidateCredentials(); |
57 | - } |
58 | - |
59 | - QSharedPointer<click::network::AccessManager> nam; |
60 | - QSharedPointer<click::CredentialsService> credentialsService; |
61 | - QSharedPointer<udm::Manager> systemDownloadManager; |
62 | - QSharedPointer<click::network::Reply> reply; |
63 | - QString downloadUrl; |
64 | - QString download_sha512; |
65 | - QString package_name; |
66 | -}; |
67 | - |
68 | -const QByteArray& click::CLICK_TOKEN_HEADER() |
69 | + |
70 | +const QByteArray& CLICK_TOKEN_HEADER() |
71 | { |
72 | static const QByteArray result("X-Click-Token"); |
73 | return result; |
74 | } |
75 | |
76 | -click::DownloadManager::DownloadManager(const QSharedPointer<click::network::AccessManager>& networkAccessManager, |
77 | - const QSharedPointer<click::CredentialsService>& credentialsService, |
78 | - const QSharedPointer<udm::Manager>& systemDownloadManager, |
79 | - QObject *parent) |
80 | - : QObject(parent), |
81 | - impl(new Private(networkAccessManager, credentialsService, systemDownloadManager)) |
82 | -{ |
83 | - QMetaObject::Connection c = connect(impl->credentialsService.data(), |
84 | - &click::CredentialsService::credentialsFound, |
85 | - this, &click::DownloadManager::handleCredentialsFound); |
86 | - if (!c) { |
87 | - qDebug() << "failed to connect to credentialsFound"; |
88 | - } |
89 | - |
90 | - c = connect(impl->credentialsService.data(), &click::CredentialsService::credentialsNotFound, |
91 | - this, &click::DownloadManager::handleCredentialsNotFound); |
92 | - if (!c) { |
93 | - qDebug() << "failed to connect to credentialsNotFound"; |
94 | - } |
95 | - |
96 | - // NOTE: using SIGNAL/SLOT macros here because new-style |
97 | - // connections are flaky on ARM. |
98 | - c = connect(impl->systemDownloadManager.data(), SIGNAL(downloadCreated(Download*)), |
99 | - this, SLOT(handleDownloadCreated(Download*))); |
100 | - |
101 | - if (!c) { |
102 | - qDebug() << "failed to connect to systemDownloadManager::downloadCreated"; |
103 | - |
104 | - } |
105 | -} |
106 | - |
107 | -click::DownloadManager::~DownloadManager(){ |
108 | -} |
109 | - |
110 | -void click::DownloadManager::startDownload(const QString& downloadUrl, const QString& download_sha512, const QString& package_name) |
111 | -{ |
112 | - impl->package_name = package_name; |
113 | - |
114 | - // NOTE: using SIGNAL/SLOT macros here because new-style |
115 | - // connections are flaky on ARM. |
116 | - QObject::connect(this, SIGNAL(clickTokenFetched(QString)), |
117 | - this, SLOT(handleClickTokenFetched(QString)), |
118 | - Qt::UniqueConnection); |
119 | - QObject::connect(this, SIGNAL(clickTokenFetchError(QString)), |
120 | - this, SLOT(handleClickTokenFetchError(QString)), |
121 | - Qt::UniqueConnection); |
122 | - fetchClickToken(downloadUrl, download_sha512); |
123 | -} |
124 | - |
125 | -void click::DownloadManager::handleClickTokenFetched(const QString& clickToken) |
126 | -{ |
127 | - QVariantMap metadata; |
128 | - |
129 | - QVariant commandline = QVariant(QStringList() << DOWNLOAD_COMMAND << "$file" << impl->package_name); |
130 | - metadata[DOWNLOAD_COMMAND_KEY] = commandline; |
131 | - metadata[DOWNLOAD_APP_ID_KEY] = impl->package_name; |
132 | - metadata["package_name"] = impl->package_name; |
133 | - |
134 | - QMap<QString, QString> headers; |
135 | - headers[CLICK_TOKEN_HEADER()] = clickToken; |
136 | - |
137 | - udm::DownloadStruct downloadStruct(impl->downloadUrl, |
138 | - impl->download_sha512, |
139 | - DOWNLOAD_MANAGER_SHA512, |
140 | - metadata, |
141 | - headers); |
142 | - |
143 | - impl->systemDownloadManager->createDownload(downloadStruct); |
144 | - |
145 | -} |
146 | - |
147 | -void click::DownloadManager::handleClickTokenFetchError(const QString& errorMessage) |
148 | -{ |
149 | - emit downloadError(errorMessage); |
150 | -} |
151 | - |
152 | -void click::DownloadManager::handleDownloadCreated(udm::Download *download) |
153 | -{ |
154 | - if (download->isError()) { |
155 | - QString error = download->error()->errorString(); |
156 | - qDebug() << "Received error from ubuntu-download-manager:" << error; |
157 | - emit downloadError(error); |
158 | - } else { |
159 | - download->start(); |
160 | - emit downloadStarted(download->id()); |
161 | - } |
162 | -} |
163 | - |
164 | -void click::DownloadManager::fetchClickToken(const QString& downloadUrl, const QString& download_sha512) |
165 | -{ |
166 | - impl->downloadUrl = downloadUrl; |
167 | - impl->download_sha512 = download_sha512; |
168 | - impl->updateCredentialsFromService(); |
169 | -} |
170 | - |
171 | -void click::DownloadManager::handleCredentialsFound(const u1::Token &token) |
172 | -{ |
173 | - qDebug() << "Credentials found, signing url " << impl->downloadUrl; |
174 | - |
175 | - QString authHeader = token.signUrl(impl->downloadUrl, QStringLiteral("HEAD")); |
176 | - |
177 | - QNetworkRequest req; |
178 | - req.setRawHeader(QStringLiteral("Authorization").toUtf8(), |
179 | - authHeader.toUtf8()); |
180 | - req.setUrl(impl->downloadUrl); |
181 | - |
182 | - impl->reply = impl->nam->head(req); |
183 | - |
184 | - // NOTE: using SIGNAL/SLOT macros here because new-style |
185 | - // connections are flaky on ARM. |
186 | - QObject::connect(impl->reply.data(), SIGNAL(error(QNetworkReply::NetworkError)), |
187 | - this, SLOT(handleNetworkError(QNetworkReply::NetworkError))); |
188 | - QObject::connect(impl->reply.data(), SIGNAL(finished()), |
189 | - this, SLOT(handleNetworkFinished())); |
190 | -} |
191 | - |
192 | -void click::DownloadManager::handleCredentialsNotFound() |
193 | -{ |
194 | - qDebug() << "No credentials were found."; |
195 | - emit credentialsNotFound(); |
196 | -} |
197 | - |
198 | -void click::DownloadManager::handleNetworkFinished() |
199 | -{ |
200 | - QVariant statusAttr = impl->reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); |
201 | - if(!statusAttr.isValid()) { |
202 | - QString msg("Invalid HTTP response."); |
203 | - qDebug() << msg; |
204 | - emit clickTokenFetchError(msg); |
205 | - return; |
206 | - } |
207 | - |
208 | - int status = statusAttr.toInt(); |
209 | - if (status != 200){ |
210 | - qDebug() << impl->reply->rawHeaderPairs(); |
211 | - qDebug() << impl->reply->readAll(); |
212 | - QString msg = QString("HTTP status not OK: %1").arg(status); |
213 | - emit clickTokenFetchError(msg); |
214 | - return; |
215 | - } |
216 | - |
217 | - if(!impl->reply->hasRawHeader(CLICK_TOKEN_HEADER())) { |
218 | - QString msg = "Response does not contain Click Header"; |
219 | - qDebug() << msg << "Full response:"; |
220 | - qDebug() << impl->reply->rawHeaderPairs(); |
221 | - qDebug() << impl->reply->readAll(); |
222 | - |
223 | - emit clickTokenFetchError(msg); |
224 | - return; |
225 | - } |
226 | - |
227 | - QString clickTokenHeaderStr = impl->reply->rawHeader(CLICK_TOKEN_HEADER()); |
228 | - |
229 | - impl->reply.reset(); |
230 | - |
231 | - emit clickTokenFetched(clickTokenHeaderStr); |
232 | -} |
233 | - |
234 | -void click::DownloadManager::handleNetworkError(QNetworkReply::NetworkError error) |
235 | -{ |
236 | - switch (error) { |
237 | - case QNetworkReply::ContentAccessDenied: |
238 | - case QNetworkReply::ContentOperationNotPermittedError: |
239 | - case QNetworkReply::AuthenticationRequiredError: |
240 | - impl->invalidateCredentialsFromService(); |
241 | - emit credentialsNotFound(); |
242 | - break; |
243 | - default: |
244 | - qDebug() << "error in network request for click token: " << error << impl->reply->errorString(); |
245 | - emit clickTokenFetchError(QString("Network Error")); |
246 | - break; |
247 | - } |
248 | - impl->reply.reset(); |
249 | -} |
250 | - |
251 | -void click::DownloadManager::getAllDownloadsWithMetadata(const QString &key, const QString &value, |
252 | - MetadataDownloadsListCb callback, |
253 | - MetadataDownloadsListCb errback) |
254 | -{ |
255 | - impl->systemDownloadManager->getAllDownloadsWithMetadata(key, value, callback, errback); |
256 | -} |
257 | - |
258 | -// Downloader |
259 | -namespace |
260 | -{ |
261 | -click::DownloadManager& downloadManagerInstance( |
262 | - const QSharedPointer<click::network::AccessManager>& networkAccessManager) |
263 | -{ |
264 | - static QSharedPointer<click::CredentialsService> ssoService |
265 | - { |
266 | - new click::CredentialsService() |
267 | - }; |
268 | - static QSharedPointer<Ubuntu::DownloadManager::Manager> udm |
269 | - { |
270 | - Ubuntu::DownloadManager::Manager::createSessionManager() |
271 | - }; |
272 | - |
273 | - static click::DownloadManager instance(networkAccessManager, |
274 | - ssoService, |
275 | - udm); |
276 | - |
277 | - return instance; |
278 | -} |
279 | -} |
280 | - |
281 | -click::Downloader::Downloader(const QSharedPointer<click::network::AccessManager>& networkAccessManager) |
282 | - : networkAccessManager(networkAccessManager) |
283 | -{ |
284 | -} |
285 | - |
286 | -click::Downloader::~Downloader() |
287 | -{ |
288 | - |
289 | -} |
290 | - |
291 | -click::DownloadManager& click::Downloader::getDownloadManager() |
292 | -{ |
293 | - return downloadManagerInstance(networkAccessManager); |
294 | -} |
295 | - |
296 | -void click::Downloader::get_download_progress(std::string package_name, const std::function<void (std::string)>& callback) |
297 | -{ |
298 | - auto& dm = getDownloadManager(); |
299 | - |
300 | - dm.getAllDownloadsWithMetadata(DOWNLOAD_APP_ID_KEY, QString::fromStdString(package_name), |
301 | - [callback, package_name](const QString& /*key*/, const QString& /*value*/, DownloadsList* downloads_list){ |
302 | +DownloadManager::DownloadManager(const QSharedPointer<click::web::Client>& client, |
303 | + const QSharedPointer<udm::Manager>& manager) : |
304 | + client(client), |
305 | + dm(manager) |
306 | +{ |
307 | +} |
308 | + |
309 | +DownloadManager::~DownloadManager() |
310 | +{ |
311 | +} |
312 | + |
313 | +void DownloadManager::get_progress(const std::string& package_name, |
314 | + const std::function<void (std::string)>& callback) |
315 | +{ |
316 | + dm->getAllDownloadsWithMetadata(DOWNLOAD_APP_ID_KEY, |
317 | + QString::fromStdString(package_name), |
318 | + [callback, package_name](const QString& /*key*/, const QString& /*value*/, DownloadsList* downloads_list){ |
319 | // got downloads matching metadata |
320 | std::string object_path; |
321 | auto downloads = downloads_list->downloads(); |
322 | @@ -339,66 +100,79 @@ |
323 | }); |
324 | } |
325 | |
326 | -namespace |
327 | -{ |
328 | -class Callback : public QObject |
329 | -{ |
330 | - Q_OBJECT |
331 | - |
332 | -public: |
333 | - Callback(const std::function<void (std::pair<std::string, click::InstallError >)>& cb) : cb(cb) |
334 | - { |
335 | - } |
336 | - |
337 | -public slots: |
338 | - void onDownloadStarted(const QString& downloadId) |
339 | - { |
340 | - cb(std::make_pair(downloadId.toUtf8().data(), click::InstallError::NoError)); |
341 | - |
342 | - // We shouldn't do this, but: We have no other indication whether a download finished or not. |
343 | - // TODO(tvoss): Remove as soon as a donwload finished signal is available. |
344 | - deleteLater(); |
345 | - } |
346 | - |
347 | - void onDownloadError(const QString& errorMessage) |
348 | - { |
349 | - cb(std::make_pair(errorMessage.toStdString(), click::InstallError::DownloadInstallError)); |
350 | - deleteLater(); |
351 | - } |
352 | - |
353 | - void onCredentialsError() |
354 | - { |
355 | - cb(std::make_pair(std::string(), click::InstallError::CredentialsError)); |
356 | - deleteLater(); |
357 | - } |
358 | - |
359 | -private: |
360 | - std::function<void (std::pair<std::string, click::InstallError >)> cb; |
361 | -}; |
362 | -} |
363 | - |
364 | -void click::Downloader::startDownload(const std::string& url, const std::string& download_sha512, const std::string& package_name, |
365 | - const std::function<void (std::pair<std::string, click::InstallError >)>& callback) |
366 | -{ |
367 | - qt::core::world::enter_with_task([this, callback, url, download_sha512, package_name] () |
368 | - { |
369 | - auto& dm = downloadManagerInstance(networkAccessManager); |
370 | - |
371 | - // Leverage automatic lifetime mgmt for QObjects here. |
372 | - auto cb = new Callback{callback}; |
373 | - |
374 | - QObject::connect(&dm, &click::DownloadManager::downloadStarted, |
375 | - cb, &Callback::onDownloadStarted); |
376 | - |
377 | - QObject::connect(&dm, &click::DownloadManager::credentialsNotFound, |
378 | - cb, &Callback::onCredentialsError); |
379 | - |
380 | - QObject::connect(&dm, &click::DownloadManager::downloadError, |
381 | - cb, &Callback::onDownloadError); |
382 | - |
383 | - dm.startDownload(QString::fromStdString(url), QString::fromStdString(download_sha512), |
384 | - QString::fromStdString(package_name)); |
385 | - }); |
386 | -} |
387 | - |
388 | -#include "download-manager.moc" |
389 | +click::web::Cancellable DownloadManager::start(const std::string& url, |
390 | + const std::string& download_sha512, |
391 | + const std::string& package_name, |
392 | + const std::function<void (std::string, Error)>& callback) |
393 | +{ |
394 | + QSharedPointer<click::web::Response> response = client->call |
395 | + (url, "HEAD", true); |
396 | + |
397 | + QObject::connect(response.data(), &click::web::Response::finished, |
398 | + [this, callback, url, download_sha512, package_name, |
399 | + response](QString) { |
400 | + auto status = response->get_status_code(); |
401 | + if (status == 200) { |
402 | + auto clickToken = response->get_header(CLICK_TOKEN_HEADER().data()); |
403 | + qDebug() << "Received click token:" << clickToken.c_str(); |
404 | + QVariantMap metadata; |
405 | + |
406 | + QVariant commandline = QVariant(QStringList() << DOWNLOAD_COMMAND << "$file" << package_name.c_str()); |
407 | + metadata[DOWNLOAD_COMMAND_KEY] = commandline; |
408 | + metadata[DOWNLOAD_APP_ID_KEY] = package_name.c_str(); |
409 | + metadata["package_name"] = package_name.c_str(); |
410 | + |
411 | + QMap<QString, QString> headers; |
412 | + headers[CLICK_TOKEN_HEADER()] = clickToken.c_str(); |
413 | + |
414 | + udm::DownloadStruct downloadStruct(url.c_str(), |
415 | + download_sha512.c_str(), |
416 | + DOWNLOAD_MANAGER_SHA512, |
417 | + metadata, |
418 | + headers); |
419 | + |
420 | + dm->createDownload(downloadStruct, |
421 | + [callback](Download* download) { |
422 | + if (download->isError()) { |
423 | + auto error = download->error()->errorString().toUtf8().data(); |
424 | + qDebug() << "Received error from ubuntu-download-manager:" << error; |
425 | + callback(error, Error::DownloadInstallError); |
426 | + } else { |
427 | + download->start(); |
428 | + callback(download->id().toUtf8().data(), Error::NoError); |
429 | + } |
430 | + }, |
431 | + [callback](Download* download) { |
432 | + callback(download->error()->errorString().toUtf8().data(), |
433 | + Error::DownloadInstallError); |
434 | + }); |
435 | + } else { |
436 | + std::string error{"Unhandled HTTP response code: "}; |
437 | + error += status; |
438 | + callback(error, Error::DownloadInstallError); |
439 | + } |
440 | + }); |
441 | + QObject::connect(response.data(), &click::web::Response::error, |
442 | + [this, callback, package_name](QString error, int error_code) { |
443 | + qDebug() << QStringLiteral("Network error (%1) fetching click token for:").arg(error_code) << package_name.c_str(); |
444 | + switch(error_code) { |
445 | + case 401: |
446 | + case 403: |
447 | + sso->invalidateCredentials(); |
448 | + callback(error.toUtf8().data(), Error::CredentialsError); |
449 | + break; |
450 | + default: |
451 | + callback(error.toUtf8().data(), Error::DownloadInstallError); |
452 | + } |
453 | + }); |
454 | + |
455 | + return click::web::Cancellable(response); |
456 | +} |
457 | + |
458 | +void DownloadManager::setCredentialsService(const QSharedPointer<click::CredentialsService>& credentialsService) |
459 | +{ |
460 | + sso = credentialsService; |
461 | + client->setCredentialsService(sso); |
462 | +} |
463 | + |
464 | +} // namespace click |
465 | |
466 | === modified file 'libclickscope/click/download-manager.h' |
467 | --- libclickscope/click/download-manager.h 2014-09-01 21:23:11 +0000 |
468 | +++ libclickscope/click/download-manager.h 2016-03-01 16:46:59 +0000 |
469 | @@ -1,5 +1,5 @@ |
470 | /* |
471 | - * Copyright (C) 2014 Canonical Ltd. |
472 | + * Copyright (C) 2014-2016 Canonical Ltd. |
473 | * |
474 | * This program is free software: you can redistribute it and/or modify it |
475 | * under the terms of the GNU General Public License version 3, as published |
476 | @@ -35,8 +35,8 @@ |
477 | #include <QObject> |
478 | #include <QString> |
479 | |
480 | -#include <click/network_access_manager.h> |
481 | #include <click/ubuntuone_credentials.h> |
482 | +#include <click/webclient.h> |
483 | |
484 | #include <ubuntu/download_manager/manager.h> |
485 | |
486 | @@ -56,60 +56,30 @@ |
487 | |
488 | const QByteArray& CLICK_TOKEN_HEADER(); |
489 | |
490 | -class DownloadManager : public QObject |
491 | + |
492 | +class DownloadManager |
493 | { |
494 | - Q_OBJECT |
495 | - |
496 | public: |
497 | - DownloadManager(const QSharedPointer<click::network::AccessManager>& networkAccessManager, |
498 | - const QSharedPointer<click::CredentialsService>& ssoService, |
499 | - const QSharedPointer<Ubuntu::DownloadManager::Manager>& systemDownloadManager, |
500 | - QObject *parent = 0); |
501 | - DownloadManager(); |
502 | + enum class Error {NoError, CredentialsError, DownloadInstallError}; |
503 | + |
504 | + DownloadManager(const QSharedPointer<click::web::Client>& client, |
505 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager); |
506 | virtual ~DownloadManager(); |
507 | |
508 | -public slots: |
509 | - virtual void startDownload(const QString& downloadUrl, const QString& download_sha512, const QString& package_name); |
510 | - virtual void fetchClickToken(const QString& downloadUrl, const QString& download_sha512); |
511 | - virtual void getAllDownloadsWithMetadata(const QString& key, |
512 | - const QString& value, |
513 | - MetadataDownloadsListCb callback, |
514 | - MetadataDownloadsListCb errback); |
515 | -signals: |
516 | - |
517 | - void credentialsNotFound(); |
518 | - void downloadStarted(const QString& downloadObjectPath); |
519 | - void downloadError(const QString& errorMessage); |
520 | - void clickTokenFetched(const QString& clickToken); |
521 | - void clickTokenFetchError(const QString& errorMessage); |
522 | - |
523 | -protected slots: |
524 | - virtual void handleCredentialsFound(const UbuntuOne::Token &token); |
525 | - virtual void handleCredentialsNotFound(); |
526 | - virtual void handleNetworkFinished(); |
527 | - virtual void handleNetworkError(QNetworkReply::NetworkError error); |
528 | - virtual void handleDownloadCreated(Download *download); |
529 | - virtual void handleClickTokenFetched(const QString& clickToken); |
530 | - virtual void handleClickTokenFetchError(const QString& errorMessage); |
531 | + virtual void get_progress(const std::string& package_name, |
532 | + const std::function<void (std::string)>& callback); |
533 | + virtual click::web::Cancellable start(const std::string& url, |
534 | + const std::string& download_sha512, |
535 | + const std::string& package_name, |
536 | + const std::function<void (std::string, |
537 | + Error)>& callback); |
538 | + |
539 | + virtual void setCredentialsService(const QSharedPointer<click::CredentialsService>& credentialsService); |
540 | |
541 | protected: |
542 | - struct Private; |
543 | - QScopedPointer<Private> impl; |
544 | -}; |
545 | - |
546 | -enum class InstallError {NoError, CredentialsError, DownloadInstallError}; |
547 | - |
548 | -class Downloader |
549 | -{ |
550 | -public: |
551 | - Downloader(const QSharedPointer<click::network::AccessManager>& networkAccessManager); |
552 | - virtual void get_download_progress(std::string package_name, const std::function<void (std::string)>& callback); |
553 | - void startDownload(const std::string& url, const std::string& download_sha512, const std::string& package_name, |
554 | - const std::function<void (std::pair<std::string, InstallError>)>& callback); |
555 | - virtual ~Downloader(); |
556 | - virtual click::DownloadManager& getDownloadManager(); |
557 | -private: |
558 | - QSharedPointer<click::network::AccessManager> networkAccessManager; |
559 | + QSharedPointer<click::web::Client> client; |
560 | + QSharedPointer<Ubuntu::DownloadManager::Manager> dm; |
561 | + QSharedPointer<click::CredentialsService> sso; |
562 | }; |
563 | |
564 | } |
565 | |
566 | === modified file 'libclickscope/click/preview.cpp' |
567 | --- libclickscope/click/preview.cpp 2016-02-08 16:24:22 +0000 |
568 | +++ libclickscope/click/preview.cpp 2016-03-01 16:46:59 +0000 |
569 | @@ -1,5 +1,5 @@ |
570 | /* |
571 | - * Copyright (C) 2014 Canonical Ltd. |
572 | + * Copyright (C) 2014-2016 Canonical Ltd. |
573 | * |
574 | * This program is free software: you can redistribute it and/or modify it |
575 | * under the terms of the GNU General Public License version 3, as published |
576 | @@ -47,6 +47,7 @@ |
577 | #include <unity/scopes/VariantBuilder.h> |
578 | #include <unity/scopes/ColumnLayout.h> |
579 | |
580 | +#include <QCoreApplication> |
581 | #include <QDebug> |
582 | |
583 | #include <functional> |
584 | @@ -167,30 +168,30 @@ |
585 | } |
586 | |
587 | void Preview::choose_strategy(const QSharedPointer<web::Client> &client, |
588 | - const QSharedPointer<click::network::AccessManager>& nam, |
589 | const QSharedPointer<pay::Package>& ppackage, |
590 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
591 | std::shared_ptr<click::DepartmentsDb> depts) |
592 | { |
593 | - strategy.reset(build_strategy(result, metadata, client, nam, ppackage, depts)); |
594 | + strategy.reset(build_strategy(result, metadata, client, ppackage, manager, depts)); |
595 | } |
596 | |
597 | PreviewStrategy* Preview::build_installing(const std::string& download_url, |
598 | const std::string& download_sha512, |
599 | const unity::scopes::Result& result, |
600 | const QSharedPointer<click::web::Client>& client, |
601 | - const QSharedPointer<click::network::AccessManager>& nam, |
602 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
603 | std::shared_ptr<click::DepartmentsDb> depts) |
604 | { |
605 | - return new InstallingPreview(download_url, download_sha512, result, client, nam, depts); |
606 | + return new InstallingPreview(download_url, download_sha512, result, client, manager, depts); |
607 | } |
608 | |
609 | |
610 | PreviewStrategy* Preview::build_strategy(const unity::scopes::Result &result, |
611 | const unity::scopes::ActionMetadata &metadata, |
612 | const QSharedPointer<web::Client> &client, |
613 | - const QSharedPointer<click::network::AccessManager>& nam, |
614 | const QSharedPointer<pay::Package>& ppackage, |
615 | - std::shared_ptr<click::DepartmentsDb> depts) |
616 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
617 | + std::shared_ptr<click::DepartmentsDb> depts) |
618 | { |
619 | if (metadata.scope_data().which() != scopes::Variant::Type::Null) { |
620 | auto metadict = metadata.scope_data().get_dict(); |
621 | @@ -210,11 +211,11 @@ |
622 | std::string download_url = metadict["download_url"].get_string(); |
623 | std::string download_sha512 = metadict["download_sha512"].get_string(); |
624 | if (action_id == click::Preview::Actions::INSTALL_CLICK) { |
625 | - return build_installing(download_url, download_sha512, result, client, nam, depts); |
626 | + return build_installing(download_url, download_sha512, result, client, manager, depts); |
627 | } else { |
628 | qWarning() << "unexpected action id " << QString::fromStdString(action_id) |
629 | << " given with download_url" << QString::fromStdString(download_url); |
630 | - return new UninstalledPreview(result, client, depts, nam, ppackage); |
631 | + return new UninstalledPreview(result, client, depts, manager, ppackage); |
632 | } |
633 | } else if (metadict.count(click::Preview::Actions::CANCEL_PURCHASE_UNINSTALLED) != 0) { |
634 | return new CancelPurchasePreview(result, false); |
635 | @@ -223,18 +224,18 @@ |
636 | } else if (metadict.count(click::Preview::Actions::UNINSTALL_CLICK) != 0) { |
637 | return new UninstallConfirmationPreview(result); |
638 | } else if (metadict.count(click::Preview::Actions::CONFIRM_UNINSTALL) != 0) { |
639 | - return new UninstallingPreview(result, client, nam, ppackage); |
640 | + return new UninstallingPreview(result, client, manager, ppackage); |
641 | } else if (metadict.count(click::Preview::Actions::CONFIRM_CANCEL_PURCHASE_UNINSTALLED) != 0) { |
642 | - return new CancellingPurchasePreview(result, client, nam, ppackage, false); |
643 | + return new CancellingPurchasePreview(result, client, ppackage, manager, false); |
644 | } else if (metadict.count(click::Preview::Actions::CONFIRM_CANCEL_PURCHASE_INSTALLED) != 0) { |
645 | - return new CancellingPurchasePreview(result, client, nam, ppackage, true); |
646 | + return new CancellingPurchasePreview(result, client, ppackage, manager, true); |
647 | } else if (metadict.count(click::Preview::Actions::RATED) != 0) { |
648 | return new InstalledPreview(result, metadata, client, ppackage, depts); |
649 | } else if (metadict.count(click::Preview::Actions::SHOW_UNINSTALLED) != 0) { |
650 | - return new UninstalledPreview(result, client, depts, nam, ppackage); |
651 | + return new UninstalledPreview(result, client, depts, manager, ppackage); |
652 | } else { |
653 | qWarning() << "preview() called with unexpected metadata. returning uninstalled preview"; |
654 | - return new UninstalledPreview(result, client, depts, nam, ppackage); |
655 | + return new UninstalledPreview(result, client, depts, manager, ppackage); |
656 | } |
657 | } else { |
658 | // metadata.scope_data() is Null, so we return an appropriate "default" preview: |
659 | @@ -245,7 +246,7 @@ |
660 | if (result["installed"].get_bool() == true) { |
661 | return new InstalledPreview(result, metadata, client, ppackage, depts); |
662 | } else { |
663 | - return new UninstalledPreview(result, client, depts, nam, ppackage); |
664 | + return new UninstalledPreview(result, client, depts, manager, ppackage); |
665 | } |
666 | } |
667 | |
668 | @@ -385,9 +386,14 @@ |
669 | |
670 | void PreviewStrategy::run_under_qt(const std::function<void ()> &task) |
671 | { |
672 | - qt::core::world::enter_with_task([task]() { |
673 | + auto _app = QCoreApplication::instance(); |
674 | + if (_app != nullptr) { |
675 | + qt::core::world::enter_with_task([task]() { |
676 | + task(); |
677 | + }); |
678 | + } else { |
679 | task(); |
680 | - }); |
681 | + } |
682 | } |
683 | |
684 | std::string get_string_maybe_null(scopes::Variant variant) |
685 | @@ -591,7 +597,7 @@ |
686 | scopes::Variant(_("Close"))); |
687 | } |
688 | |
689 | -scopes::PreviewWidgetList PreviewStrategy::loginErrorWidgets(const PackageDetails& details) |
690 | +scopes::PreviewWidgetList PreviewStrategy::loginErrorWidgets(const std::string& download_url, const std::string& download_sha512) |
691 | { |
692 | auto widgets = errorWidgets(scopes::Variant(_("Login Error")), |
693 | scopes::Variant(_("Please log in to your Ubuntu One account.")), |
694 | @@ -605,8 +611,8 @@ |
695 | { |
696 | {"id", scopes::Variant(click::Preview::Actions::INSTALL_CLICK)}, |
697 | {"label", scopes::Variant(_("Go to Accounts"))}, |
698 | - {"download_url", scopes::Variant(details.download_url)}, |
699 | - {"download_sha512", scopes::Variant(details.download_sha512)}, |
700 | + {"download_url", scopes::Variant(download_url)}, |
701 | + {"download_sha512", scopes::Variant(download_sha512)}, |
702 | }); |
703 | buttons.add_attribute_value("actions", builder.end()); |
704 | oa_client.register_account_login_item(buttons, |
705 | @@ -698,13 +704,14 @@ |
706 | const std::string &download_sha512, |
707 | const unity::scopes::Result &result, |
708 | const QSharedPointer<click::web::Client>& client, |
709 | - const QSharedPointer<click::network::AccessManager> &nam, |
710 | - std::shared_ptr<click::DepartmentsDb> depts) |
711 | - : PreviewStrategy(result, client), DepartmentUpdater(depts), |
712 | - download_url(download_url), |
713 | - download_sha512(download_sha512), |
714 | - downloader(new click::Downloader(nam)), |
715 | - depts_db(depts) |
716 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
717 | + std::shared_ptr<click::DepartmentsDb> depts) : |
718 | + PreviewStrategy(result, client), |
719 | + DepartmentUpdater(depts), |
720 | + download_url(download_url), |
721 | + download_sha512(download_sha512), |
722 | + dm(new DownloadManager(client, manager)), |
723 | + depts_db(depts) |
724 | { |
725 | } |
726 | |
727 | @@ -724,49 +731,57 @@ |
728 | void InstallingPreview::run(const unity::scopes::PreviewReplyProxy &reply) |
729 | { |
730 | qDebug() << "Starting installation" << QString(download_url.c_str()) << QString(download_sha512.c_str()); |
731 | - downloader->startDownload(download_url, download_sha512, result["name"].get_string(), |
732 | - [this, reply] (std::pair<std::string, click::InstallError> rc){ |
733 | - // NOTE: details not needed by fooErrorWidgets, so no need to populateDetails(): |
734 | - bool login_error = false; |
735 | - switch (rc.second) |
736 | - { |
737 | - case InstallError::DownloadInstallError: |
738 | - qWarning() << "Error received from UDM during startDownload:" << rc.first.c_str(); |
739 | - reply->push(downloadErrorWidgets()); |
740 | - return; |
741 | - case InstallError::CredentialsError: |
742 | - qWarning() << "InstallingPreview got error in getting credentials during startDownload"; |
743 | - login_error = true; |
744 | - default: |
745 | - std::string object_path = rc.first; |
746 | - qDebug() << "Successfully created UDM Download."; |
747 | - populateDetails([this, reply, object_path, login_error](const PackageDetails &details) { |
748 | - store_department(details); |
749 | - if (login_error) { |
750 | - reply->push(loginErrorWidgets(details)); |
751 | - } else { |
752 | - pushPackagePreviewWidgets(cachedWidgets, details, progressBarWidget(object_path)); |
753 | - startLauncherAnimation(details); |
754 | - } |
755 | - }, |
756 | - [this, reply, login_error](const ReviewList& reviewlist, |
757 | - click::Reviews::Error error) { |
758 | - if (!login_error) { |
759 | - if (error == click::Reviews::Error::NoError) { |
760 | - auto const revs = reviewsWidgets(reviewlist); |
761 | - cachedWidgets.push(revs); |
762 | - cachedWidgets.layout.appendToColumn(cachedWidgets.layout.singleColumn.column1, revs); |
763 | - cachedWidgets.layout.appendToColumn(cachedWidgets.layout.twoColumns.column1, revs); |
764 | - } else { |
765 | - qDebug() << "There was an error getting reviews for:" << result["name"].get_string().c_str(); |
766 | - } |
767 | - } |
768 | - cachedWidgets.flush(reply); |
769 | - reply->finished(); |
770 | + std::promise<bool> promise; |
771 | + auto future = promise.get_future(); |
772 | + run_under_qt([this, reply, &promise]() { |
773 | + QSharedPointer<click::CredentialsService> sso(new click::CredentialsService()); |
774 | + dm->setCredentialsService(sso); |
775 | + dm->start(download_url, download_sha512, result["name"].get_string(), |
776 | + [this, reply, &promise] (std::string msg, DownloadManager::Error dmerr){ |
777 | + switch (dmerr) |
778 | + { |
779 | + case DownloadManager::Error::DownloadInstallError: |
780 | + qWarning() << "Error received from UDM during startDownload:" << msg.c_str(); |
781 | + reply->push(downloadErrorWidgets()); |
782 | + promise.set_value(false); |
783 | + break; |
784 | + case DownloadManager::Error::CredentialsError: |
785 | + qWarning() << "InstallingPreview got error in getting credentials during startDownload"; |
786 | + reply->push(loginErrorWidgets(download_url, download_sha512)); |
787 | + promise.set_value(false); |
788 | + break; |
789 | + case DownloadManager::Error::NoError: { |
790 | + std::string object_path = msg; |
791 | + qDebug() << "Successfully created UDM Download."; |
792 | + populateDetails([this, reply, object_path](const PackageDetails &details) { |
793 | + store_department(details); |
794 | + pushPackagePreviewWidgets(cachedWidgets, details, progressBarWidget(object_path)); |
795 | + startLauncherAnimation(details); |
796 | + }, |
797 | + [this, reply, &promise](const ReviewList& reviewlist, |
798 | + click::Reviews::Error error) { |
799 | + if (error == click::Reviews::Error::NoError) { |
800 | + auto const revs = reviewsWidgets(reviewlist); |
801 | + cachedWidgets.push(revs); |
802 | + cachedWidgets.layout.appendToColumn(cachedWidgets.layout.singleColumn.column1, revs); |
803 | + cachedWidgets.layout.appendToColumn(cachedWidgets.layout.twoColumns.column1, revs); |
804 | + } else { |
805 | + qDebug() << "There was an error getting reviews for:" << result["name"].get_string().c_str(); |
806 | + } |
807 | + cachedWidgets.flush(reply); |
808 | + promise.set_value(true); |
809 | + }); |
810 | + break; |
811 | + } |
812 | + default: |
813 | + qCritical() << "Unknown error occurred downloading."; |
814 | + promise.set_value(false); |
815 | + break; |
816 | + } |
817 | }); |
818 | - break; |
819 | - } |
820 | - }); |
821 | + }); |
822 | + future.get(); |
823 | + reply->finished(); |
824 | } |
825 | |
826 | scopes::PreviewWidgetList PreviewStrategy::progressBarWidget(const std::string& object_path) |
827 | @@ -1195,19 +1210,14 @@ |
828 | |
829 | // class UninstalledPreview |
830 | |
831 | -click::Downloader* UninstalledPreview::get_downloader(const QSharedPointer<click::network::AccessManager>& nam) |
832 | -{ |
833 | - static auto downloader = new click::Downloader(nam); |
834 | - return downloader; |
835 | -} |
836 | - |
837 | UninstalledPreview::UninstalledPreview(const unity::scopes::Result& result, |
838 | const QSharedPointer<click::web::Client>& client, |
839 | const std::shared_ptr<click::DepartmentsDb>& depts, |
840 | - const QSharedPointer<click::network::AccessManager>& nam, |
841 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
842 | const QSharedPointer<pay::Package>& ppackage) |
843 | : PreviewStrategy(result, client, ppackage), |
844 | - DepartmentUpdater(depts), nam(nam) |
845 | + DepartmentUpdater(depts), |
846 | + dm(new DownloadManager(client, manager)) |
847 | { |
848 | qDebug() << "Creating new UninstalledPreview for result" << QString::fromStdString(result["name"].get_string()); |
849 | } |
850 | @@ -1226,8 +1236,8 @@ |
851 | [this, reply](const ReviewList& reviewlist, |
852 | click::Reviews::Error reviewserror) { |
853 | std::string app_name = result["name"].get_string(); |
854 | - get_downloader(nam)->get_download_progress(app_name, |
855 | - [this, reply, reviewlist, reviewserror](std::string object_path){ |
856 | + dm->get_progress(app_name, |
857 | + [this, reply, reviewlist, reviewserror](std::string object_path){ |
858 | found_object_path = object_path; |
859 | scopes::PreviewWidgetList button_widgets; |
860 | if(found_object_path.empty()) { |
861 | @@ -1304,9 +1314,9 @@ |
862 | // TODO: this class should be removed once uninstall() is handled elsewhere. |
863 | UninstallingPreview::UninstallingPreview(const unity::scopes::Result& result, |
864 | const QSharedPointer<click::web::Client>& client, |
865 | - const QSharedPointer<click::network::AccessManager>& nam, |
866 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
867 | const QSharedPointer<pay::Package>& ppackage) |
868 | - : UninstalledPreview(result, client, nullptr, nam, ppackage) |
869 | + : UninstalledPreview(result, client, nullptr, manager, ppackage) |
870 | { |
871 | } |
872 | |
873 | @@ -1347,10 +1357,10 @@ |
874 | |
875 | CancellingPurchasePreview::CancellingPurchasePreview(const unity::scopes::Result& result, |
876 | const QSharedPointer<click::web::Client>& client, |
877 | - const QSharedPointer<click::network::AccessManager>& nam, |
878 | const QSharedPointer<pay::Package>& ppackage, |
879 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
880 | bool installed) |
881 | - : UninstallingPreview(result, client, nam, ppackage), |
882 | + : UninstallingPreview(result, client, manager, ppackage), |
883 | installed(installed) |
884 | { |
885 | } |
886 | |
887 | === modified file 'libclickscope/click/preview.h' |
888 | --- libclickscope/click/preview.h 2016-02-08 16:24:22 +0000 |
889 | +++ libclickscope/click/preview.h 2016-03-01 16:46:59 +0000 |
890 | @@ -105,14 +105,14 @@ |
891 | PreviewStrategy* build_strategy(const unity::scopes::Result& result, |
892 | const unity::scopes::ActionMetadata& metadata, |
893 | const QSharedPointer<web::Client> &client, |
894 | - const QSharedPointer<click::network::AccessManager>& nam, |
895 | const QSharedPointer<pay::Package>& ppackage, |
896 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
897 | std::shared_ptr<click::DepartmentsDb> depts); |
898 | virtual PreviewStrategy* build_installing(const std::string& download_url, |
899 | const std::string& download_sha512, |
900 | const unity::scopes::Result& result, |
901 | const QSharedPointer<click::web::Client>& client, |
902 | - const QSharedPointer<click::network::AccessManager>& nam, |
903 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
904 | std::shared_ptr<click::DepartmentsDb> depts); |
905 | public: |
906 | UNITY_DEFINES_PTRS(Preview); |
907 | @@ -145,8 +145,8 @@ |
908 | const unity::scopes::ActionMetadata& metadata); |
909 | virtual ~Preview(); |
910 | void choose_strategy(const QSharedPointer<web::Client> &client, |
911 | - const QSharedPointer<click::network::AccessManager>& nam, |
912 | const QSharedPointer<pay::Package>& ppackage, |
913 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
914 | std::shared_ptr<click::DepartmentsDb> depts); |
915 | // From unity::scopes::PreviewQuery |
916 | void cancelled() override; |
917 | @@ -181,7 +181,7 @@ |
918 | virtual scopes::PreviewWidgetList progressBarWidget(const std::string& object_path); |
919 | virtual scopes::PreviewWidgetList reviewsWidgets(const click::ReviewList &reviewlist); |
920 | virtual scopes::PreviewWidgetList downloadErrorWidgets(); |
921 | - virtual scopes::PreviewWidgetList loginErrorWidgets(const PackageDetails& details); |
922 | + virtual scopes::PreviewWidgetList loginErrorWidgets(const std::string& download_url, const std::string& download_sha512); |
923 | virtual scopes::PreviewWidgetList errorWidgets(const scopes::Variant& title, |
924 | const scopes::Variant& subtitle, |
925 | const scopes::Variant& action_id, |
926 | @@ -228,7 +228,7 @@ |
927 | const std::string& download_sha512, |
928 | const unity::scopes::Result& result, |
929 | const QSharedPointer<click::web::Client>& client, |
930 | - const QSharedPointer<click::network::AccessManager>& nam, |
931 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
932 | std::shared_ptr<click::DepartmentsDb> depts); |
933 | |
934 | virtual ~InstallingPreview(); |
935 | @@ -238,7 +238,7 @@ |
936 | protected: |
937 | std::string download_url; |
938 | std::string download_sha512; |
939 | - QSharedPointer<click::Downloader> downloader; |
940 | + QSharedPointer<click::DownloadManager> dm; |
941 | std::shared_ptr<click::DepartmentsDb> depts_db; |
942 | CachedPreviewWidgets cachedWidgets; |
943 | void startLauncherAnimation(const PackageDetails& details); |
944 | @@ -314,12 +314,11 @@ |
945 | |
946 | class UninstalledPreview : public PreviewStrategy, public DepartmentUpdater |
947 | { |
948 | - const QSharedPointer<click::network::AccessManager>& nam; |
949 | public: |
950 | UninstalledPreview(const unity::scopes::Result& result, |
951 | const QSharedPointer<click::web::Client>& client, |
952 | const std::shared_ptr<click::DepartmentsDb>& depts, |
953 | - const QSharedPointer<click::network::AccessManager>& nam, |
954 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
955 | const QSharedPointer<pay::Package>& ppackage); |
956 | |
957 | virtual ~UninstalledPreview(); |
958 | @@ -329,8 +328,9 @@ |
959 | PackageDetails found_details; |
960 | CachedPreviewWidgets cachedWidgets; |
961 | std::string found_object_path; |
962 | - virtual click::Downloader* get_downloader(const QSharedPointer<click::network::AccessManager>& nam); |
963 | virtual scopes::PreviewWidgetList uninstalledActionButtonWidgets(const PackageDetails &details); |
964 | + |
965 | + QSharedPointer<click::DownloadManager> dm; |
966 | }; |
967 | |
968 | // TODO: this is only necessary to perform uninstall. |
969 | @@ -340,7 +340,7 @@ |
970 | public: |
971 | UninstallingPreview(const unity::scopes::Result& result, |
972 | const QSharedPointer<click::web::Client>& client, |
973 | - const QSharedPointer<click::network::AccessManager>& nam, |
974 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
975 | const QSharedPointer<pay::Package>& ppackage); |
976 | |
977 | virtual ~UninstallingPreview(); |
978 | @@ -357,8 +357,8 @@ |
979 | public: |
980 | CancellingPurchasePreview(const unity::scopes::Result& result, |
981 | const QSharedPointer<click::web::Client>& client, |
982 | - const QSharedPointer<click::network::AccessManager>& nam, |
983 | const QSharedPointer<pay::Package>& ppackage, |
984 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
985 | bool installed); |
986 | |
987 | virtual ~CancellingPurchasePreview(); |
988 | |
989 | === modified file 'libclickscope/click/webclient.cpp' |
990 | --- libclickscope/click/webclient.cpp 2016-02-01 16:09:55 +0000 |
991 | +++ libclickscope/click/webclient.cpp 2016-03-01 16:46:59 +0000 |
992 | @@ -82,7 +82,7 @@ |
993 | const std::string& iri, |
994 | const click::web::CallParams& params) |
995 | { |
996 | - return call(iri, "GET", false, |
997 | + return call(iri, "GET", true, |
998 | std::map<std::string, std::string>(), "", params); |
999 | } |
1000 | |
1001 | @@ -118,9 +118,13 @@ |
1002 | QByteArray verb(method.c_str(), method.length()); |
1003 | // |
1004 | // for 'get' use get method of access manager explicitly as sendCustomRequest disables the use of cache. |
1005 | - auto reply = (method == "GET" && buffer->size() == 0) ? |
1006 | - impl->network_access_manager->get(*request) : |
1007 | - impl->network_access_manager->sendCustomRequest(*request, verb, buffer.data()); |
1008 | + auto reply = ((method == "GET" && buffer->size() == 0) ? |
1009 | + impl->network_access_manager->get(*request) : |
1010 | + (method == "HEAD") ? |
1011 | + impl->network_access_manager->head(*request) : |
1012 | + impl->network_access_manager->sendCustomRequest(*request, |
1013 | + verb, |
1014 | + buffer.data())); |
1015 | responsePtr->setReply(reply); |
1016 | }; |
1017 | |
1018 | @@ -159,6 +163,15 @@ |
1019 | impl->setCredentialsService(sso); |
1020 | } |
1021 | |
1022 | +void click::web::Client::invalidateCredentials() |
1023 | +{ |
1024 | + if (impl->sso.isNull()) { |
1025 | + qCritical() << "Request to delete credentials, but no sso object available."; |
1026 | + return; |
1027 | + } |
1028 | + impl->sso->invalidateCredentials(); |
1029 | +} |
1030 | + |
1031 | click::web::Response::Response(const QSharedPointer<QNetworkRequest>& request, |
1032 | const QSharedPointer<QBuffer>& buffer, |
1033 | QObject* parent) |
1034 | |
1035 | === modified file 'libclickscope/click/webclient.h' |
1036 | --- libclickscope/click/webclient.h 2016-02-01 16:09:55 +0000 |
1037 | +++ libclickscope/click/webclient.h 2016-03-01 16:46:59 +0000 |
1038 | @@ -121,11 +121,12 @@ |
1039 | virtual QSharedPointer<Response> call( |
1040 | const std::string& iri, |
1041 | const std::string& method, |
1042 | - bool sign = false, |
1043 | + bool sign = true, |
1044 | const std::map<std::string, std::string>& headers = std::map<std::string, std::string>(), |
1045 | const std::string& data = "", |
1046 | const CallParams& params = CallParams()); |
1047 | void setCredentialsService(const QSharedPointer<click::CredentialsService>& sso); |
1048 | + virtual void invalidateCredentials(); |
1049 | |
1050 | private: |
1051 | struct Private; |
1052 | |
1053 | === modified file 'libclickscope/tests/mock_ubuntu_download_manager.h' |
1054 | --- libclickscope/tests/mock_ubuntu_download_manager.h 2015-12-11 15:38:08 +0000 |
1055 | +++ libclickscope/tests/mock_ubuntu_download_manager.h 2016-03-01 16:46:59 +0000 |
1056 | @@ -1,5 +1,5 @@ |
1057 | /* |
1058 | - * Copyright (C) 2014 Canonical Ltd. |
1059 | + * Copyright (C) 2014-2016 Canonical Ltd. |
1060 | * |
1061 | * This program is free software: you can redistribute it and/or modify it |
1062 | * under the terms of the GNU General Public License version 3, as published |
1063 | @@ -34,9 +34,11 @@ |
1064 | #include <QDBusObjectPath> |
1065 | |
1066 | #include <ubuntu/download_manager/download.h> |
1067 | +#include <ubuntu/download_manager/downloads_list.h> |
1068 | #include <ubuntu/download_manager/error.h> |
1069 | #include <ubuntu/download_manager/manager.h> |
1070 | |
1071 | +#include <gmock/gmock.h> |
1072 | |
1073 | class MockDownload : public Ubuntu::DownloadManager::Download |
1074 | { |
1075 | @@ -87,6 +89,17 @@ |
1076 | MOCK_METHOD0(errorString, QString()); |
1077 | }; |
1078 | |
1079 | +class MockDownloadsList : public Ubuntu::DownloadManager::DownloadsList |
1080 | +{ |
1081 | +public: |
1082 | + |
1083 | + MockDownloadsList() : Ubuntu::DownloadManager::DownloadsList() {}; |
1084 | + |
1085 | + MOCK_CONST_METHOD0(downloads, QList<QSharedPointer<Ubuntu::DownloadManager::Download>>()); |
1086 | + MOCK_CONST_METHOD0(isError, bool()); |
1087 | + MOCK_CONST_METHOD0(error, Ubuntu::DownloadManager::Error*()); |
1088 | +}; |
1089 | + |
1090 | class MockSystemDownloadManager : public Ubuntu::DownloadManager::Manager |
1091 | { |
1092 | public: |
1093 | |
1094 | === modified file 'libclickscope/tests/mock_webclient.h' |
1095 | --- libclickscope/tests/mock_webclient.h 2014-10-01 15:27:44 +0000 |
1096 | +++ libclickscope/tests/mock_webclient.h 2016-03-01 16:46:59 +0000 |
1097 | @@ -87,13 +87,13 @@ |
1098 | QSharedPointer<click::web::Response> call( |
1099 | const std::string& iri, |
1100 | const click::web::CallParams& params=click::web::CallParams()) override { |
1101 | - return callImpl(iri, "GET", false, |
1102 | + return callImpl(iri, "GET", true, |
1103 | std::map<std::string, std::string>(), "", params); |
1104 | } |
1105 | QSharedPointer<click::web::Response> call( |
1106 | const std::string& iri, |
1107 | const std::string& method, |
1108 | - bool sign = false, |
1109 | + bool sign = true, |
1110 | const std::map<std::string, std::string>& headers = std::map<std::string, std::string>(), |
1111 | const std::string& data = "", |
1112 | const click::web::CallParams& params=click::web::CallParams()) override { |
1113 | @@ -102,6 +102,7 @@ |
1114 | |
1115 | MOCK_METHOD1(has_header, bool(const std::string& header)); |
1116 | MOCK_METHOD1(get_header, std::string(const std::string&header)); |
1117 | + MOCK_METHOD0(invalidateCredentials, void()); |
1118 | }; |
1119 | |
1120 | } |
1121 | |
1122 | === modified file 'libclickscope/tests/test_download_manager.cpp' |
1123 | --- libclickscope/tests/test_download_manager.cpp 2014-08-21 13:21:24 +0000 |
1124 | +++ libclickscope/tests/test_download_manager.cpp 2016-03-01 16:46:59 +0000 |
1125 | @@ -1,5 +1,5 @@ |
1126 | /* |
1127 | - * Copyright (C) 2014 Canonical Ltd. |
1128 | + * Copyright (C) 2014-2016 Canonical Ltd. |
1129 | * |
1130 | * This program is free software: you can redistribute it and/or modify it |
1131 | * under the terms of the GNU General Public License version 3, as published |
1132 | @@ -27,36 +27,20 @@ |
1133 | * files in the program, then also delete it here. |
1134 | */ |
1135 | |
1136 | -#include <QDBusObjectPath> |
1137 | -#include <QCoreApplication> |
1138 | -#include <QDebug> |
1139 | -#include <QString> |
1140 | -#include <QStringBuilder> |
1141 | - |
1142 | -#include <QThread> |
1143 | -#include <QTimer> |
1144 | - |
1145 | -#include <token.h> |
1146 | - |
1147 | -#include <gmock/gmock.h> |
1148 | -#include <gtest/gtest.h> |
1149 | - |
1150 | #include <click/download-manager.h> |
1151 | #include <tests/mock_network_access_manager.h> |
1152 | +#include <tests/mock_webclient.h> |
1153 | +#include <tests/mock_ubuntu_download_manager.h> |
1154 | #include <tests/mock_ubuntuone_credentials.h> |
1155 | |
1156 | -#include "mock_ubuntu_download_manager.h" |
1157 | +#include <gtest/gtest.h> |
1158 | +#include <memory> |
1159 | |
1160 | using namespace ::testing; |
1161 | |
1162 | namespace udm = Ubuntu::DownloadManager; |
1163 | #include <ubuntu/download_manager/download_struct.h> |
1164 | |
1165 | -void PrintTo(const QString& str, ::std::ostream* os) |
1166 | -{ |
1167 | - *os << "QString(\"" << str.toStdString() << "\")"; |
1168 | -} |
1169 | - |
1170 | namespace |
1171 | { |
1172 | const QString TEST_URL("http://test.local/"); |
1173 | @@ -67,421 +51,172 @@ |
1174 | const QString TEST_DOWNLOAD_ID("/com/ubuntu/download_manager/test"); |
1175 | const QString TEST_DOWNLOADERROR_STRING("test downloadError string"); |
1176 | |
1177 | -struct CredsNetworkTestParameters |
1178 | -{ |
1179 | -public: |
1180 | - CredsNetworkTestParameters(bool credsFound = true, bool replySignalsError = false, |
1181 | - int replyStatusCode = 200, bool replyHasClickRawHeader = true, |
1182 | - bool expectSuccessSignal = true) |
1183 | - : credsFound(credsFound), replySignalsError(replySignalsError), replyStatusCode(replyStatusCode), |
1184 | - replyHasClickRawHeader(replyHasClickRawHeader), expectSuccessSignal(expectSuccessSignal) {}; |
1185 | - |
1186 | - bool credsFound; |
1187 | - bool replySignalsError; |
1188 | - int replyStatusCode; |
1189 | - bool replyHasClickRawHeader; |
1190 | - bool expectSuccessSignal; |
1191 | -}; |
1192 | - |
1193 | -::std::ostream& operator<<(::std::ostream& os, const CredsNetworkTestParameters& p) |
1194 | -{ |
1195 | - return os << "creds[" << (p.credsFound ? "x" : " ") << "] " |
1196 | - << "replySignalsError[" << (p.replySignalsError ? "x" : " ") << "] " |
1197 | - << "statusCode[" << p.replyStatusCode << "] " |
1198 | - << "replyHasClickRawHeader[" << (p.replyHasClickRawHeader ? "x" : " ") << "] " |
1199 | - << "expectSuccessSignal[" << (p.expectSuccessSignal ? "x" : " ") << "] "; |
1200 | -} |
1201 | - |
1202 | - |
1203 | -struct StartDownloadTestParameters |
1204 | -{ |
1205 | -public: |
1206 | - StartDownloadTestParameters(bool clickTokenFetchSignalsError = false, |
1207 | - bool downloadSignalsError = false, |
1208 | - bool expectSuccessSignal = true) |
1209 | - : clickTokenFetchSignalsError(clickTokenFetchSignalsError), |
1210 | - downloadSignalsError(downloadSignalsError), |
1211 | - expectSuccessSignal(expectSuccessSignal) {}; |
1212 | - |
1213 | - bool clickTokenFetchSignalsError; |
1214 | - bool downloadSignalsError; |
1215 | - bool expectSuccessSignal; |
1216 | -}; |
1217 | - |
1218 | -::std::ostream& operator<<(::std::ostream& os, const StartDownloadTestParameters& p) |
1219 | -{ |
1220 | - return os << "clickTokenFetchSignalsError[" << (p.clickTokenFetchSignalsError ? "x" : " ") << "] " |
1221 | - << "downloadSignalsError[" << (p.downloadSignalsError ? "x" : " ") << "] " |
1222 | - << "expectSuccessSignal[" << (p.expectSuccessSignal ? "x" : " ") << "] "; |
1223 | -} |
1224 | - |
1225 | - |
1226 | -struct DownloadManagerTestBase |
1227 | -{ |
1228 | - DownloadManagerTestBase() |
1229 | - : app(argc, argv), |
1230 | - mockNam(new MockNetworkAccessManager()), |
1231 | - mockCredentialsService(new MockCredentialsService()), |
1232 | - mockReplyPtr(&mockReply, [](click::network::Reply*) {}), |
1233 | - mockSystemDownloadManager(new MockSystemDownloadManager()) |
1234 | - { |
1235 | - signalTimer.setSingleShot(true); |
1236 | - testTimeout.setSingleShot(true); |
1237 | - |
1238 | - QObject::connect( |
1239 | - &testTimeout, &QTimer::timeout, |
1240 | - [this]() { app.quit(); FAIL() << "Operation timed out."; } ); |
1241 | - } |
1242 | - |
1243 | - void SetUp() |
1244 | - { |
1245 | - const int oneSecondInMsec = 1000; |
1246 | - testTimeout.start(10 * oneSecondInMsec); |
1247 | - } |
1248 | - |
1249 | - void Quit() |
1250 | - { |
1251 | - app.quit(); |
1252 | - } |
1253 | - |
1254 | - int argc = 0; |
1255 | - char** argv = nullptr; |
1256 | - QCoreApplication app; |
1257 | - QTimer testTimeout; |
1258 | - QTimer signalTimer; |
1259 | - QSharedPointer<MockNetworkAccessManager> mockNam; |
1260 | - QSharedPointer<MockCredentialsService> mockCredentialsService; |
1261 | - ::testing::NiceMock<MockNetworkReply> mockReply; |
1262 | - QSharedPointer<click::network::Reply> mockReplyPtr; |
1263 | - QSharedPointer<MockSystemDownloadManager> mockSystemDownloadManager; |
1264 | -}; |
1265 | - |
1266 | -struct DISABLED_DownloadManagerStartDownloadTest : public DownloadManagerTestBase, |
1267 | - public ::testing::TestWithParam<StartDownloadTestParameters> |
1268 | -{ |
1269 | -public: |
1270 | -}; |
1271 | - |
1272 | -struct DISABLED_DownloadManagerCredsNetworkTest : public DownloadManagerTestBase, |
1273 | - public ::testing::TestWithParam<CredsNetworkTestParameters> |
1274 | -{ |
1275 | -public: |
1276 | - |
1277 | - void signalEmptyTokenFromMockCredsService() |
1278 | - { |
1279 | - UbuntuOne::Token token; |
1280 | - mockCredentialsService->credentialsFound(token); |
1281 | - } |
1282 | - |
1283 | - void signalErrorAfterDelay() |
1284 | - { |
1285 | - // delay emitting this signal so that the download manager has |
1286 | - // time to connect to the signal first, as the (mock)Reply is |
1287 | - // returned by the (mock)Nam. |
1288 | - QObject::connect(&signalTimer, &QTimer::timeout, [this]() |
1289 | - { |
1290 | - mockReplyPtr->error(QNetworkReply::UnknownNetworkError); |
1291 | - }); |
1292 | - signalTimer.start(10); |
1293 | - } |
1294 | - |
1295 | - void signalFinishedAfterDelay() |
1296 | - { |
1297 | - QObject::connect(&signalTimer, &QTimer::timeout, [this]() |
1298 | - { |
1299 | - mockReplyPtr->finished(); |
1300 | - }); |
1301 | - signalTimer.start(10); |
1302 | - } |
1303 | -}; |
1304 | - |
1305 | -struct DownloadManagerMockClient |
1306 | -{ |
1307 | - MOCK_METHOD0(onCredentialsNotFoundEmitted, void()); |
1308 | - MOCK_METHOD1(onClickTokenFetchedEmitted, void(QString clickToken)); |
1309 | - MOCK_METHOD1(onClickTokenFetchErrorEmitted, void(QString errorMessage)); |
1310 | - MOCK_METHOD1(onDownloadStartedEmitted, void(QString id)); |
1311 | - MOCK_METHOD1(onDownloadErrorEmitted, void(QString errorMessage)); |
1312 | -}; |
1313 | - |
1314 | -} // anon namespace |
1315 | - |
1316 | - |
1317 | -TEST_P(DISABLED_DownloadManagerCredsNetworkTest, TestFetchClickToken) |
1318 | -{ |
1319 | - using namespace ::testing; |
1320 | - |
1321 | - CredsNetworkTestParameters p = GetParam(); |
1322 | - |
1323 | - QList<QPair<QByteArray, QByteArray> > emptyHeaderPairs; |
1324 | - ON_CALL(mockReply, rawHeaderPairs()).WillByDefault(Return(emptyHeaderPairs)); |
1325 | - ON_CALL(mockReply, readAll()).WillByDefault(Return(QByteArray("bogus readAll() return"))); |
1326 | - |
1327 | - if (p.credsFound) { |
1328 | - |
1329 | - EXPECT_CALL(*mockCredentialsService, getCredentials()) |
1330 | - .Times(1).WillOnce( |
1331 | - InvokeWithoutArgs(this, |
1332 | - &DISABLED_DownloadManagerCredsNetworkTest::signalEmptyTokenFromMockCredsService)); |
1333 | - |
1334 | - if (p.replySignalsError) { |
1335 | - EXPECT_CALL(*mockNam, head(_)).WillOnce( |
1336 | - DoAll( |
1337 | - InvokeWithoutArgs(this, &DISABLED_DownloadManagerCredsNetworkTest::signalErrorAfterDelay), |
1338 | - Return(mockReplyPtr))); |
1339 | - EXPECT_CALL(mockReply, errorString()).Times(1).WillOnce(Return(QString("Bogus error for tests"))); |
1340 | - |
1341 | - } else { |
1342 | - EXPECT_CALL(*mockNam, head(_)).WillOnce( |
1343 | - DoAll( |
1344 | - InvokeWithoutArgs(this, &DISABLED_DownloadManagerCredsNetworkTest::signalFinishedAfterDelay), |
1345 | - Return(mockReplyPtr))); |
1346 | - |
1347 | - EXPECT_CALL(mockReply, attribute(QNetworkRequest::HttpStatusCodeAttribute)) |
1348 | - .Times(1).WillOnce(Return(QVariant(p.replyStatusCode))); |
1349 | - |
1350 | - if (p.replyStatusCode == 200) { |
1351 | - EXPECT_CALL(mockReply, hasRawHeader(click::CLICK_TOKEN_HEADER())) |
1352 | - .Times(1).WillOnce(Return(p.replyHasClickRawHeader)); |
1353 | - |
1354 | - if (p.replyHasClickRawHeader) { |
1355 | - EXPECT_CALL(mockReply, rawHeader(click::CLICK_TOKEN_HEADER())) |
1356 | - .Times(1).WillOnce(Return(TEST_HEADER_VALUE)); |
1357 | - } |
1358 | - } |
1359 | - |
1360 | - } |
1361 | - |
1362 | - } else { |
1363 | - EXPECT_CALL(*mockCredentialsService, getCredentials()) |
1364 | - .Times(1).WillOnce(InvokeWithoutArgs(mockCredentialsService.data(), |
1365 | - &MockCredentialsService::credentialsNotFound)); |
1366 | - |
1367 | - EXPECT_CALL(*mockNam, head(_)).Times(0); |
1368 | - } |
1369 | - |
1370 | - click::DownloadManager dm(mockNam, mockCredentialsService, |
1371 | - mockSystemDownloadManager); |
1372 | - |
1373 | - DownloadManagerMockClient mockDownloadManagerClient; |
1374 | - |
1375 | - QObject::connect(&dm, &click::DownloadManager::credentialsNotFound, |
1376 | - [&mockDownloadManagerClient]() |
1377 | - { |
1378 | - mockDownloadManagerClient.onCredentialsNotFoundEmitted(); |
1379 | - }); |
1380 | - |
1381 | - QObject::connect(&dm, &click::DownloadManager::clickTokenFetchError, |
1382 | - [&mockDownloadManagerClient](const QString& error) |
1383 | - { |
1384 | - mockDownloadManagerClient.onClickTokenFetchErrorEmitted(error); |
1385 | - }); |
1386 | - |
1387 | - |
1388 | - QObject::connect(&dm, &click::DownloadManager::clickTokenFetched, |
1389 | - [&mockDownloadManagerClient](const QString& token) |
1390 | - { |
1391 | - mockDownloadManagerClient.onClickTokenFetchedEmitted(token); |
1392 | - }); |
1393 | - |
1394 | - if (p.expectSuccessSignal) { |
1395 | - |
1396 | - EXPECT_CALL(mockDownloadManagerClient, onClickTokenFetchedEmitted(TEST_HEADER_VALUE)) |
1397 | - .Times(1) |
1398 | - .WillOnce( |
1399 | - InvokeWithoutArgs( |
1400 | - this, |
1401 | - &DISABLED_DownloadManagerCredsNetworkTest::Quit)); |
1402 | - |
1403 | - EXPECT_CALL(mockDownloadManagerClient, onClickTokenFetchErrorEmitted(_)).Times(0); |
1404 | - |
1405 | - } else { |
1406 | - |
1407 | - if (p.credsFound) { |
1408 | - |
1409 | - EXPECT_CALL(mockDownloadManagerClient, onClickTokenFetchErrorEmitted(_)) |
1410 | - .Times(1) |
1411 | - .WillOnce( |
1412 | - InvokeWithoutArgs( |
1413 | - this, |
1414 | - &DISABLED_DownloadManagerCredsNetworkTest::Quit)); |
1415 | - } else { |
1416 | - |
1417 | - EXPECT_CALL(mockDownloadManagerClient, onCredentialsNotFoundEmitted()) |
1418 | - .Times(1) |
1419 | - .WillOnce( |
1420 | - InvokeWithoutArgs( |
1421 | - this, |
1422 | - &DISABLED_DownloadManagerCredsNetworkTest::Quit)); |
1423 | - } |
1424 | - |
1425 | - EXPECT_CALL(mockDownloadManagerClient, onClickTokenFetchedEmitted(_)).Times(0); |
1426 | - |
1427 | - } |
1428 | - |
1429 | - // Now start the function we're testing, after a delay. This is |
1430 | - // awkwardly verbose because QTimer::singleShot doesn't accept |
1431 | - // arguments or lambdas. |
1432 | - |
1433 | - // We need to delay the call until after the app.exec() call so |
1434 | - // that when we call app.quit() on success, there is a running app |
1435 | - // to quit. |
1436 | - QTimer timer; |
1437 | - timer.setSingleShot(true); |
1438 | - QObject::connect(&timer, &QTimer::timeout, [&dm]() { |
1439 | - dm.fetchClickToken(TEST_URL, TEST_SHA512); |
1440 | - } ); |
1441 | - timer.start(0); |
1442 | - |
1443 | - // now exec the app so events can proceed: |
1444 | - app.exec(); |
1445 | -} |
1446 | - |
1447 | -INSTANTIATE_TEST_CASE_P(DownloadManagerCredsNetworkTests, DISABLED_DownloadManagerCredsNetworkTest, |
1448 | - ::testing::Values( |
1449 | - // CredsNetworkTestParameters(credsFound, replySignalsError, replyStatusCode, replyHasClickRawHeader, expectSuccessSignal) |
1450 | - CredsNetworkTestParameters(true, false, 200, true, true), // success |
1451 | - CredsNetworkTestParameters(true, true, 200, true, false), // misc QNetworkReply error => error |
1452 | - CredsNetworkTestParameters(true, false, 200, false, false), // no header => error |
1453 | - CredsNetworkTestParameters(true, false, 401, true, false), // HTTP error status => error |
1454 | - CredsNetworkTestParameters(false, false, 200, true, false) // no creds => error |
1455 | - )); |
1456 | - |
1457 | - |
1458 | -MATCHER(DownloadStructIsValid, "Download Struct does not match expected") |
1459 | -{ |
1460 | - auto commandList = arg.getMetadata()["post-download-command"].toStringList(); |
1461 | - return arg.getUrl() == TEST_URL |
1462 | - && arg.getHash() == "" |
1463 | - && arg.getAlgorithm() == "" |
1464 | - && arg.getMetadata()["app_id"] == QVariant(TEST_APP_ID) |
1465 | - && commandList[0] == "/bin/sh" |
1466 | - && commandList[1] == "-c" |
1467 | - && commandList[3] == "$file" |
1468 | - && arg.getHeaders()["X-Click-Token"] == TEST_CLICK_TOKEN_VALUE; |
1469 | -} |
1470 | - |
1471 | - |
1472 | -TEST_P(DISABLED_DownloadManagerStartDownloadTest, TestStartDownload) |
1473 | -{ |
1474 | - using namespace ::testing; |
1475 | - |
1476 | - StartDownloadTestParameters p = GetParam(); |
1477 | - |
1478 | - click::DownloadManager dm(mockNam, mockCredentialsService, |
1479 | - mockSystemDownloadManager); |
1480 | - |
1481 | - // mockError is heap-allocated because downloadWithError will delete it. |
1482 | - MockError mockError; // = new MockError(); |
1483 | - NiceMock<MockDownload> downloadWithError(&mockError); |
1484 | - ON_CALL(downloadWithError, isError()).WillByDefault(Return(true)); |
1485 | - ON_CALL(downloadWithError, error()).WillByDefault(Return(&mockError)); |
1486 | - NiceMock<MockDownload> successfulDownload; |
1487 | - ON_CALL(successfulDownload, isError()).WillByDefault(Return(false)); |
1488 | - |
1489 | - // Just directly signal clickTokenFetched or error from |
1490 | - // getCredentials(), no need to re-test the same code as the |
1491 | - // previous test |
1492 | - |
1493 | - std::function<void()> clickTokenSignalFunc; |
1494 | - if (p.clickTokenFetchSignalsError) { |
1495 | - clickTokenSignalFunc = std::function<void()>([&](){ |
1496 | - dm.clickTokenFetchError(TEST_DOWNLOADERROR_STRING); |
1497 | - }); |
1498 | - EXPECT_CALL(*mockSystemDownloadManager, createDownload(_)).Times(0); |
1499 | - |
1500 | - } else { |
1501 | - clickTokenSignalFunc = std::function<void()>([&](){ |
1502 | - dm.clickTokenFetched(TEST_CLICK_TOKEN_VALUE); |
1503 | - }); |
1504 | - |
1505 | - std::function<void()> downloadCreatedSignalFunc; |
1506 | - |
1507 | - // NOTE: udm::Download doesn't have virtual functions, so mocking |
1508 | - // them doesn't work and we have to construct objects that will |
1509 | - // behave correctly without mock return values, using overridden constructors: |
1510 | - if (p.downloadSignalsError) { |
1511 | - |
1512 | - EXPECT_CALL(mockError, errorString()).Times(1).WillOnce(Return(TEST_DOWNLOADERROR_STRING)); |
1513 | - downloadCreatedSignalFunc = std::function<void()>([&](){ |
1514 | - mockSystemDownloadManager->downloadCreated(&downloadWithError); |
1515 | - }); |
1516 | - |
1517 | - } else { |
1518 | - EXPECT_CALL(mockError, errorString()).Times(0); |
1519 | - downloadCreatedSignalFunc = std::function<void()>([&](){ |
1520 | - mockSystemDownloadManager->downloadCreated(&successfulDownload); |
1521 | - }); |
1522 | - } |
1523 | - |
1524 | - EXPECT_CALL(*mockSystemDownloadManager, |
1525 | - createDownload(DownloadStructIsValid())).Times(1).WillOnce(InvokeWithoutArgs(downloadCreatedSignalFunc)); |
1526 | - } |
1527 | - |
1528 | - EXPECT_CALL(*mockCredentialsService, getCredentials()) |
1529 | - .Times(1).WillOnce(InvokeWithoutArgs(clickTokenSignalFunc)); |
1530 | - |
1531 | - |
1532 | - DownloadManagerMockClient mockDownloadManagerClient; |
1533 | - |
1534 | - QObject::connect(&dm, &click::DownloadManager::downloadError, |
1535 | - [&mockDownloadManagerClient](const QString& error) |
1536 | - { |
1537 | - mockDownloadManagerClient.onDownloadErrorEmitted(error); |
1538 | - }); |
1539 | - |
1540 | - |
1541 | - QObject::connect(&dm, &click::DownloadManager::downloadStarted, |
1542 | - [&mockDownloadManagerClient](const QString& downloadId) |
1543 | - { |
1544 | - qDebug() << "in lambda connected to click::dm::downloadstarted"; |
1545 | - |
1546 | - mockDownloadManagerClient.onDownloadStartedEmitted(downloadId); |
1547 | - }); |
1548 | - |
1549 | - if (p.expectSuccessSignal) { |
1550 | - |
1551 | - EXPECT_CALL(mockDownloadManagerClient, onDownloadStartedEmitted(TEST_DOWNLOAD_ID)) |
1552 | - .Times(1) |
1553 | - .WillOnce( |
1554 | - InvokeWithoutArgs( |
1555 | - this, |
1556 | - &DISABLED_DownloadManagerStartDownloadTest::Quit)); |
1557 | - |
1558 | - EXPECT_CALL(mockDownloadManagerClient, onDownloadErrorEmitted(_)).Times(0); |
1559 | - EXPECT_CALL(successfulDownload, id()).Times(1).WillOnce(Return(TEST_DOWNLOAD_ID)); |
1560 | - EXPECT_CALL(successfulDownload, start()).Times(1); |
1561 | - |
1562 | - |
1563 | - } else { |
1564 | - |
1565 | - EXPECT_CALL(mockDownloadManagerClient, onDownloadErrorEmitted(TEST_DOWNLOADERROR_STRING)) |
1566 | - .Times(1) |
1567 | - .WillOnce( |
1568 | - InvokeWithoutArgs( |
1569 | - this, |
1570 | - &DISABLED_DownloadManagerStartDownloadTest::Quit)); |
1571 | - |
1572 | - EXPECT_CALL(mockDownloadManagerClient, onDownloadStartedEmitted(_)).Times(0); |
1573 | - |
1574 | - } |
1575 | - |
1576 | - QTimer timer; |
1577 | - timer.setSingleShot(true); |
1578 | - QObject::connect(&timer, &QTimer::timeout, [&dm]() { |
1579 | - dm.startDownload(TEST_URL, TEST_SHA512, TEST_APP_ID); |
1580 | - } ); |
1581 | - timer.start(0); |
1582 | - |
1583 | - // now exec the app so events can proceed: |
1584 | - app.exec(); |
1585 | - |
1586 | -} |
1587 | - |
1588 | -INSTANTIATE_TEST_CASE_P(DownloadManagerStartDownloadTests, DISABLED_DownloadManagerStartDownloadTest, |
1589 | - ::testing::Values( |
1590 | - // params: (clickTokenFetchSignalsError, downloadSignalsError, expectSuccessSignal) |
1591 | - StartDownloadTestParameters(false, false, true), |
1592 | - StartDownloadTestParameters(true, false, false), |
1593 | - StartDownloadTestParameters(false, true, false) |
1594 | - )); |
1595 | + |
1596 | +class DownloadManagerTest : public ::testing::Test |
1597 | +{ |
1598 | +protected: |
1599 | + QSharedPointer<MockClient> clientPtr; |
1600 | + QSharedPointer<MockNetworkAccessManager> namPtr; |
1601 | + QSharedPointer<MockSystemDownloadManager> sdmPtr; |
1602 | + QSharedPointer<MockCredentialsService> ssoPtr; |
1603 | + std::shared_ptr<click::DownloadManager> dmPtr; |
1604 | + |
1605 | + virtual void SetUp() |
1606 | + { |
1607 | + namPtr.reset(new MockNetworkAccessManager()); |
1608 | + clientPtr.reset(new NiceMock<MockClient>(namPtr)); |
1609 | + clientPtr->setCredentialsService(ssoPtr); |
1610 | + dmPtr.reset(new click::DownloadManager(clientPtr, sdmPtr)); |
1611 | + } |
1612 | + |
1613 | + MOCK_METHOD2(start_callback, void(std::string, click::DownloadManager::Error)); |
1614 | + MOCK_METHOD1(progress_callback, void(std::string)); |
1615 | +}; |
1616 | + |
1617 | +} |
1618 | + |
1619 | +TEST_F(DownloadManagerTest, testStartCallsWebservice) |
1620 | +{ |
1621 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1622 | + auto response = responseForReply(reply.asSharedPtr()); |
1623 | + |
1624 | + EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1625 | + .Times(1) |
1626 | + .WillOnce(Return(response)); |
1627 | + |
1628 | + dmPtr->start("", "", "", |
1629 | + [](std::string, click::DownloadManager::Error) {}); |
1630 | +} |
1631 | + |
1632 | +TEST_F(DownloadManagerTest, testStartCallbackCalled) |
1633 | +{ |
1634 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1635 | + auto response = responseForReply(reply.asSharedPtr()); |
1636 | + |
1637 | + EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(0))); |
1638 | + EXPECT_CALL(reply.instance, readAll()) |
1639 | + .Times(1) |
1640 | + .WillOnce(Return("")); |
1641 | + EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1642 | + .Times(1) |
1643 | + .WillOnce(Return(response)); |
1644 | + EXPECT_CALL(*this, start_callback(_, _)).Times(1); |
1645 | + |
1646 | + dmPtr->start("", "", "", |
1647 | + [this](std::string msg, click::DownloadManager::Error err) { |
1648 | + start_callback(msg, err); |
1649 | + }); |
1650 | + response->replyFinished(); |
1651 | +} |
1652 | + |
1653 | +TEST_F(DownloadManagerTest, testStartHTTPForbidden) |
1654 | +{ |
1655 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1656 | + auto response = responseForReply(reply.asSharedPtr()); |
1657 | + |
1658 | + EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(403))); |
1659 | + EXPECT_CALL(reply.instance, readAll()) |
1660 | + .Times(1) |
1661 | + .WillOnce(Return("")); |
1662 | + EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1663 | + .Times(1) |
1664 | + .WillOnce(Return(response)); |
1665 | + EXPECT_CALL(*this, start_callback(StartsWith("Unhandled HTTP response code:"), |
1666 | + click::DownloadManager::Error::DownloadInstallError)).Times(1); |
1667 | + |
1668 | + dmPtr->start("", "", "", |
1669 | + [this](std::string msg, click::DownloadManager::Error err) { |
1670 | + start_callback(msg, err); |
1671 | + }); |
1672 | + response->replyFinished(); |
1673 | +} |
1674 | + |
1675 | +TEST_F(DownloadManagerTest, testStartHTTPError) |
1676 | +{ |
1677 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1678 | + auto response = responseForReply(reply.asSharedPtr()); |
1679 | + |
1680 | + EXPECT_CALL(reply.instance, errorString()) |
1681 | + .WillOnce(Return(QString("ERROR"))); |
1682 | + EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(404))); |
1683 | + EXPECT_CALL(reply.instance, readAll()) |
1684 | + .Times(1) |
1685 | + .WillOnce(Return("")); |
1686 | + EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1687 | + .Times(1) |
1688 | + .WillOnce(Return(response)); |
1689 | + EXPECT_CALL(*this, start_callback("ERROR (203)", |
1690 | + click::DownloadManager::Error::DownloadInstallError)).Times(1); |
1691 | + |
1692 | + dmPtr->start("", "", "", |
1693 | + [this](std::string msg, click::DownloadManager::Error err) { |
1694 | + start_callback(msg, err); |
1695 | + }); |
1696 | + response->errorHandler(QNetworkReply::ContentNotFoundError); |
1697 | +} |
1698 | + |
1699 | +TEST_F(DownloadManagerTest, testStartCredentialsError) |
1700 | +{ |
1701 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1702 | + auto response = responseForReply(reply.asSharedPtr()); |
1703 | + |
1704 | + QSharedPointer<MockCredentialsService> sso(new MockCredentialsService()); |
1705 | + dmPtr->setCredentialsService(sso); |
1706 | + |
1707 | + EXPECT_CALL(reply.instance, errorString()) |
1708 | + .WillOnce(Return(QString("ERROR"))); |
1709 | + EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(401))); |
1710 | + EXPECT_CALL(reply.instance, readAll()) |
1711 | + .Times(1) |
1712 | + .WillOnce(Return("")); |
1713 | + EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1714 | + .Times(1) |
1715 | + .WillOnce(Return(response)); |
1716 | + EXPECT_CALL(*(sso.data()), invalidateCredentials()); |
1717 | + EXPECT_CALL(*this, start_callback("ERROR (201)", |
1718 | + click::DownloadManager::Error::CredentialsError)).Times(1); |
1719 | + |
1720 | + dmPtr->start("", "", "test.package", |
1721 | + [this](std::string msg, click::DownloadManager::Error err) { |
1722 | + start_callback(msg, err); |
1723 | + }); |
1724 | + response->errorHandler(QNetworkReply::ContentAccessDenied); |
1725 | +} |
1726 | + |
1727 | +// FIXME: createDownload() SEGV under tests |
1728 | +TEST_F(DownloadManagerTest, DISABLED_testStartDownloadCreated) |
1729 | +{ |
1730 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1731 | + auto response = responseForReply(reply.asSharedPtr()); |
1732 | + |
1733 | + EXPECT_CALL(reply.instance, rawHeader(QByteArray("X-Click-Token"))) |
1734 | + .Times(1) |
1735 | + .WillOnce(Return(QString("clicktoken"))); |
1736 | + EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(200))); |
1737 | + EXPECT_CALL(reply.instance, readAll()) |
1738 | + .Times(1) |
1739 | + .WillOnce(Return("")); |
1740 | + EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _)) |
1741 | + .Times(1) |
1742 | + .WillOnce(Return(response)); |
1743 | + |
1744 | + EXPECT_CALL(*sdmPtr, createDownload(_, _, _)); |
1745 | + dmPtr->start("", "", "test.package", |
1746 | + [this](std::string msg, click::DownloadManager::Error err) { |
1747 | + start_callback(msg, err); |
1748 | + }); |
1749 | + response->replyFinished(); |
1750 | +} |
1751 | + |
1752 | +// FIXME: getAllDownloadsWithMetadata() SEGV under tests |
1753 | +TEST_F(DownloadManagerTest, DISABLED_testGetProgressNoDownloads) |
1754 | +{ |
1755 | + EXPECT_CALL(*sdmPtr, getAllDownloadsWithMetadata(_, _, _, _)) |
1756 | + .Times(1) |
1757 | + .WillOnce(InvokeArgument<3>(QStringLiteral(""), QStringLiteral(""), |
1758 | + nullptr)); |
1759 | + dmPtr->get_progress("com.example.test", |
1760 | + [this](std::string object_path) { |
1761 | + progress_callback(object_path); |
1762 | + }); |
1763 | +} |
1764 | |
1765 | === modified file 'libclickscope/tests/test_index.cpp' |
1766 | --- libclickscope/tests/test_index.cpp 2016-01-21 23:25:38 +0000 |
1767 | +++ libclickscope/tests/test_index.cpp 2016-03-01 16:46:59 +0000 |
1768 | @@ -1,5 +1,5 @@ |
1769 | /* |
1770 | - * Copyright (C) 2014 Canonical Ltd. |
1771 | + * Copyright (C) 2014-2016 Canonical Ltd. |
1772 | * |
1773 | * This program is free software: you can redistribute it and/or modify it |
1774 | * under the terms of the GNU General Public License version 3, as published |
1775 | @@ -190,6 +190,18 @@ |
1776 | indexPtr->departments("departments", [](const click::DepartmentList&, const click::HighlightList&, click::Index::Error, int) {}); |
1777 | } |
1778 | |
1779 | +TEST_F(IndexTest, testDetailsSignsCall) |
1780 | +{ |
1781 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1782 | + auto response = responseForReply(reply.asSharedPtr()); |
1783 | + |
1784 | + EXPECT_CALL(*clientPtr, callImpl(_, _, true, _, _, _)) |
1785 | + .Times(1) |
1786 | + .WillOnce(Return(response)); |
1787 | + |
1788 | + indexPtr->get_details("fake-app", [](const click::PackageDetails, click::Index::Error) {}); |
1789 | +} |
1790 | + |
1791 | TEST_F(IndexTest, testSearchSendsRightPath) |
1792 | { |
1793 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
1794 | |
1795 | === modified file 'libclickscope/tests/test_preview.cpp' |
1796 | --- libclickscope/tests/test_preview.cpp 2016-01-28 14:37:39 +0000 |
1797 | +++ libclickscope/tests/test_preview.cpp 2016-03-01 16:46:59 +0000 |
1798 | @@ -27,19 +27,23 @@ |
1799 | * files in the program, then also delete it here. |
1800 | */ |
1801 | |
1802 | -#include <time.h> |
1803 | - |
1804 | -#include <unity/scopes/testing/MockPreviewReply.h> |
1805 | -#include <unity/scopes/testing/Result.h> |
1806 | - |
1807 | -#include <gtest/gtest.h> |
1808 | #include <click/preview.h> |
1809 | -#include <fake_json.h> |
1810 | -#include <mock_pay.h> |
1811 | + |
1812 | #include <click/index.h> |
1813 | #include <click/interface.h> |
1814 | #include <click/reviews.h> |
1815 | +#include <fake_json.h> |
1816 | +#include <mock_pay.h> |
1817 | +#include <mock_ubuntu_download_manager.h> |
1818 | + |
1819 | +#include <QCoreApplication> |
1820 | +#include <QTimer> |
1821 | + |
1822 | #include <boost/locale/time_zone.hpp> |
1823 | +#include <gtest/gtest.h> |
1824 | +#include <time.h> |
1825 | +#include <unity/scopes/testing/MockPreviewReply.h> |
1826 | +#include <unity/scopes/testing/Result.h> |
1827 | |
1828 | using namespace ::testing; |
1829 | using ::testing::Matcher; |
1830 | @@ -346,8 +350,8 @@ |
1831 | unity::scopes::ActionMetadata metadata; |
1832 | unity::scopes::VariantMap metadict; |
1833 | QSharedPointer<click::web::Client> client; |
1834 | - QSharedPointer<click::network::AccessManager> nam; |
1835 | QSharedPointer<MockPayPackage> pay_package; |
1836 | + QSharedPointer<MockSystemDownloadManager> dm; |
1837 | std::shared_ptr<click::DepartmentsDb> depts; |
1838 | const std::string FAKE_SHA512 = "FAKE_SHA512"; |
1839 | |
1840 | @@ -364,9 +368,13 @@ |
1841 | |
1842 | } |
1843 | |
1844 | - MOCK_METHOD6(build_installing, click::PreviewStrategy*(const std::string&, const std::string&, |
1845 | - const unity::scopes::Result&, const QSharedPointer<click::web::Client>&, |
1846 | - const QSharedPointer<click::network::AccessManager>&, std::shared_ptr<click::DepartmentsDb>)); |
1847 | + MOCK_METHOD6(build_installing, |
1848 | + click::PreviewStrategy*(const std::string&, |
1849 | + const std::string&, |
1850 | + const unity::scopes::Result&, |
1851 | + const QSharedPointer<click::web::Client>&, |
1852 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>&, |
1853 | + std::shared_ptr<click::DepartmentsDb>)); |
1854 | }; |
1855 | |
1856 | TEST_F(StrategyChooserTest, testSha512IsUsed) { |
1857 | @@ -376,7 +384,7 @@ |
1858 | metadata.set_scope_data(unity::scopes::Variant(metadict)); |
1859 | MockablePreview preview(result, metadata); |
1860 | EXPECT_CALL(preview, build_installing(_, FAKE_SHA512, _, _, _, _)); |
1861 | - preview.choose_strategy(client, nam, pay_package, depts); |
1862 | + preview.choose_strategy(client, pay_package, dm, depts); |
1863 | } |
1864 | |
1865 | |
1866 | @@ -386,53 +394,25 @@ |
1867 | click::PackageDetails details; |
1868 | unity::scopes::PreviewWidgetList widgets; |
1869 | QSharedPointer<click::web::Client> client; |
1870 | - QSharedPointer<click::network::AccessManager> nam; |
1871 | QSharedPointer<MockPayPackage> pay_package; |
1872 | + QSharedPointer<MockSystemDownloadManager> sdm; |
1873 | std::shared_ptr<click::DepartmentsDb> depts; |
1874 | unity::scopes::testing::MockPreviewReply reply; |
1875 | std::shared_ptr<unity::scopes::testing::MockPreviewReply> replyptr{&reply, [](unity::scopes::testing::MockPreviewReply*){}}; |
1876 | }; |
1877 | |
1878 | -class FakeDownloader : public click::Downloader { |
1879 | - std::string object_path; |
1880 | - std::function<void (std::string)> callback; |
1881 | -public: |
1882 | - FakeDownloader(const std::string& object_path, const QSharedPointer<click::network::AccessManager>& networkAccessManager) |
1883 | - : click::Downloader(networkAccessManager), object_path(object_path) |
1884 | - { |
1885 | - |
1886 | - } |
1887 | - void get_download_progress(std::string /*package_name*/, const std::function<void (std::string)> &callback) |
1888 | - { |
1889 | - this->callback = callback; |
1890 | - } |
1891 | - |
1892 | - void activate_callback() |
1893 | - { |
1894 | - callback(object_path); |
1895 | - } |
1896 | -}; |
1897 | - |
1898 | class FakeBaseUninstalledPreview : public click::UninstalledPreview { |
1899 | std::string object_path; |
1900 | public: |
1901 | - std::unique_ptr<FakeDownloader> fake_downloader; |
1902 | FakeBaseUninstalledPreview(const std::string& object_path, |
1903 | const unity::scopes::Result& result, |
1904 | const QSharedPointer<click::web::Client>& client, |
1905 | const std::shared_ptr<click::DepartmentsDb>& depts, |
1906 | - const QSharedPointer<click::network::AccessManager>& nam, |
1907 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
1908 | const QSharedPointer<pay::Package> pay_package) |
1909 | - : click::UninstalledPreview(result, client, depts, nam, pay_package), |
1910 | - object_path(object_path), |
1911 | - fake_downloader(new FakeDownloader(object_path, nam)) |
1912 | - { |
1913 | - |
1914 | - } |
1915 | - |
1916 | - virtual click::Downloader* get_downloader(const QSharedPointer<click::network::AccessManager> &/*nam*/) |
1917 | - { |
1918 | - return fake_downloader.get(); |
1919 | + : click::UninstalledPreview(result, client, depts, manager, pay_package), |
1920 | + object_path(object_path) |
1921 | + { |
1922 | } |
1923 | |
1924 | void populateDetails(std::function<void (const click::PackageDetails &)> details_callback, |
1925 | @@ -451,39 +431,38 @@ |
1926 | const unity::scopes::Result& result, |
1927 | const QSharedPointer<click::web::Client>& client, |
1928 | const std::shared_ptr<click::DepartmentsDb>& depts, |
1929 | - const QSharedPointer<click::network::AccessManager>& nam, |
1930 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
1931 | const QSharedPointer<pay::Package> pay_package) |
1932 | - : FakeBaseUninstalledPreview(object_path, result, client, depts, nam, pay_package) { |
1933 | + : FakeBaseUninstalledPreview(object_path, result, client, depts, manager, pay_package) { |
1934 | } |
1935 | }; |
1936 | |
1937 | |
1938 | -TEST_F(UninstalledPreviewTest, testDownloadInProgress) { |
1939 | +// FIXME: Needs Qt main loop |
1940 | +TEST_F(UninstalledPreviewTest, DISABLED_testDownloadInProgress) { |
1941 | std::string fake_object_path = "/fake/object/path"; |
1942 | |
1943 | result["name"] = "fake_app_name"; |
1944 | scopes::PreviewWidgetList response; |
1945 | - FakeUninstalledPreview preview(fake_object_path, result, client, depts, nam, pay_package); |
1946 | + FakeUninstalledPreview preview(fake_object_path, result, client, depts, sdm, pay_package); |
1947 | EXPECT_CALL(preview, progressBarWidget(_)) |
1948 | .Times(1) |
1949 | .WillOnce(Return(response)); |
1950 | EXPECT_CALL(*replyptr, register_layout(_)); |
1951 | preview.run(replyptr); |
1952 | - preview.fake_downloader->activate_callback(); |
1953 | } |
1954 | |
1955 | -TEST_F(UninstalledPreviewTest, testNoDownloadProgress) { |
1956 | +// FIXME: Needs Qt main loop |
1957 | +TEST_F(UninstalledPreviewTest, DISABLED_testNoDownloadProgress) { |
1958 | std::string fake_object_path = ""; |
1959 | |
1960 | result["name"] = "fake_app_name"; |
1961 | scopes::PreviewWidgetList response; |
1962 | - FakeUninstalledPreview preview(fake_object_path, result, client, depts, nam, pay_package); |
1963 | + FakeUninstalledPreview preview(fake_object_path, result, client, depts, sdm, pay_package); |
1964 | EXPECT_CALL(preview, uninstalledActionButtonWidgets(_)) |
1965 | .Times(1) |
1966 | .WillOnce(Return(response)); |
1967 | - EXPECT_CALL(*replyptr, register_layout(_)); |
1968 | preview.run(replyptr); |
1969 | - preview.fake_downloader->activate_callback(); |
1970 | } |
1971 | |
1972 | class FakeUninstalledRefundablePreview : FakeBaseUninstalledPreview { |
1973 | @@ -491,9 +470,9 @@ |
1974 | FakeUninstalledRefundablePreview(const unity::scopes::Result& result, |
1975 | const QSharedPointer<click::web::Client>& client, |
1976 | const std::shared_ptr<click::DepartmentsDb>& depts, |
1977 | - const QSharedPointer<click::network::AccessManager>& nam, |
1978 | + const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager, |
1979 | const QSharedPointer<pay::Package> pay_package) |
1980 | - : FakeBaseUninstalledPreview(std::string{""}, result, client, depts, nam, pay_package){ |
1981 | + : FakeBaseUninstalledPreview(std::string{""}, result, client, depts, manager, pay_package){ |
1982 | } |
1983 | using click::UninstalledPreview::uninstalledActionButtonWidgets; |
1984 | MOCK_METHOD0(isRefundable, bool()); |
1985 | @@ -514,7 +493,7 @@ |
1986 | result["name"] = "fake_app_name"; |
1987 | result["price"] = 2.99; |
1988 | result["purchased"] = true; |
1989 | - FakeUninstalledRefundablePreview preview(result, client, depts, nam, pay_package); |
1990 | + FakeUninstalledRefundablePreview preview(result, client, depts, sdm, pay_package); |
1991 | |
1992 | click::PackageDetails pkgdetails; |
1993 | EXPECT_CALL(preview, isRefundable()).Times(1) |
1994 | @@ -527,7 +506,7 @@ |
1995 | result["name"] = "fake_app_name"; |
1996 | result["price"] = 2.99; |
1997 | result["purchased"] = true; |
1998 | - FakeUninstalledRefundablePreview preview(result, client, depts, nam, pay_package); |
1999 | + FakeUninstalledRefundablePreview preview(result, client, depts, sdm, pay_package); |
2000 | |
2001 | click::PackageDetails pkgdetails; |
2002 | EXPECT_CALL(preview, isRefundable()).Times(1) |
2003 | @@ -542,7 +521,6 @@ |
2004 | unity::scopes::ActionMetadata metadata; |
2005 | unity::scopes::VariantMap metadict; |
2006 | QSharedPointer<click::web::Client> client; |
2007 | - QSharedPointer<click::network::AccessManager> nam; |
2008 | QSharedPointer<MockPayPackage> pay_package; |
2009 | std::shared_ptr<click::DepartmentsDb> depts; |
2010 | |
2011 | |
2012 | === modified file 'libclickscope/tests/test_reviews.cpp' |
2013 | --- libclickscope/tests/test_reviews.cpp 2016-01-21 20:43:16 +0000 |
2014 | +++ libclickscope/tests/test_reviews.cpp 2016-03-01 16:46:59 +0000 |
2015 | @@ -150,6 +150,19 @@ |
2016 | click::Reviews::Error) {}); |
2017 | } |
2018 | |
2019 | +TEST_F(ReviewsTest, testFetchReviewsSignsCall) |
2020 | +{ |
2021 | + LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
2022 | + auto response = responseForReply(reply.asSharedPtr()); |
2023 | + |
2024 | + EXPECT_CALL(*clientPtr, callImpl(_, _, true, _, _, _)) |
2025 | + .Times(1) |
2026 | + .WillOnce(Return(response)); |
2027 | + |
2028 | + reviewsPtr->fetch_reviews("", [](click::ReviewList, |
2029 | + click::Reviews::Error) {}); |
2030 | +} |
2031 | + |
2032 | TEST_F(ReviewsTest, testFetchReviewsSendsQueryAsParam) |
2033 | { |
2034 | LifetimeHelper<click::network::Reply, MockNetworkReply> reply; |
2035 | |
2036 | === modified file 'libclickscope/tests/test_webclient.cpp' |
2037 | --- libclickscope/tests/test_webclient.cpp 2014-10-17 17:07:31 +0000 |
2038 | +++ libclickscope/tests/test_webclient.cpp 2016-03-01 16:46:59 +0000 |
2039 | @@ -231,7 +231,7 @@ |
2040 | .WillOnce(Return(replyPtr)); |
2041 | |
2042 | auto wr = wc.call(FAKE_SERVER + FAKE_PATH, |
2043 | - "HEAD", true); |
2044 | + "POST", true); |
2045 | } |
2046 | |
2047 | TEST_F(WebClientTest, testSignedCredentialsServiceUnset) |
2048 | @@ -244,13 +244,13 @@ |
2049 | |
2050 | click::web::Client wc(namPtr); |
2051 | |
2052 | - EXPECT_CALL(nam, sendCustomRequest(_, _, _)) |
2053 | + EXPECT_CALL(nam, get(_)) |
2054 | .Times(1) |
2055 | .WillOnce(Return(replyPtr)); |
2056 | EXPECT_CALL(*reply, errorString()).Times(1).WillOnce(Return("auth failed")); |
2057 | |
2058 | auto response = wc.call(FAKE_SERVER + FAKE_PATH, |
2059 | - "HEAD", true); |
2060 | + "GET", true); |
2061 | QObject::connect(response.data(), &click::web::Response::error, |
2062 | [this](QString desc){ |
2063 | errorHandler(desc); |
2064 | @@ -279,7 +279,7 @@ |
2065 | .WillOnce(Return(replyPtr)); |
2066 | |
2067 | auto wr = wc.call(FAKE_SERVER + FAKE_PATH, |
2068 | - "HEAD", true); |
2069 | + "POST", true); |
2070 | } |
2071 | |
2072 | |
2073 | |
2074 | === modified file 'scope/clickapps/apps-scope.cpp' |
2075 | --- scope/clickapps/apps-scope.cpp 2015-11-24 18:23:23 +0000 |
2076 | +++ scope/clickapps/apps-scope.cpp 2016-03-01 16:46:59 +0000 |
2077 | @@ -27,6 +27,9 @@ |
2078 | * files in the program, then also delete it here. |
2079 | */ |
2080 | |
2081 | +#include "apps-scope.h" |
2082 | +#include "apps-query.h" |
2083 | + |
2084 | #include <click/qtbridge.h> |
2085 | #include <click/preview.h> |
2086 | #include <click/interface.h> |
2087 | @@ -42,9 +45,6 @@ |
2088 | #include <unity/scopes/CannedQuery.h> |
2089 | #include <unity/scopes/ActivationResponse.h> |
2090 | |
2091 | -#include "apps-scope.h" |
2092 | -#include "apps-query.h" |
2093 | - |
2094 | using namespace click; |
2095 | |
2096 | click::Scope::Scope() |
2097 | @@ -81,6 +81,9 @@ |
2098 | static const int zero = 0; |
2099 | auto emptyCb = [this]() |
2100 | { |
2101 | + sso.reset(new click::CredentialsService()); |
2102 | + client->setCredentialsService(sso); |
2103 | + dm.reset(Ubuntu::DownloadManager::Manager::createSessionManager()); |
2104 | }; |
2105 | |
2106 | qt::core::world::build_and_run(zero, nullptr, emptyCb); |
2107 | @@ -101,7 +104,7 @@ |
2108 | const unity::scopes::ActionMetadata& metadata) { |
2109 | qDebug() << "Scope::preview() called."; |
2110 | auto preview = new click::Preview(result, metadata); |
2111 | - preview->choose_strategy(client, nam, pay_package, depts_db); |
2112 | + preview->choose_strategy(client, pay_package, dm, depts_db); |
2113 | return unity::scopes::PreviewQueryBase::UPtr{preview}; |
2114 | } |
2115 | |
2116 | |
2117 | === modified file 'scope/clickapps/apps-scope.h' |
2118 | --- scope/clickapps/apps-scope.h 2015-11-24 18:23:23 +0000 |
2119 | +++ scope/clickapps/apps-scope.h 2016-03-01 16:46:59 +0000 |
2120 | @@ -35,6 +35,7 @@ |
2121 | #include <click/pay.h> |
2122 | #include <click/webclient.h> |
2123 | |
2124 | +#include <ubuntu/download_manager/manager.h> |
2125 | #include <unity/scopes/ScopeBase.h> |
2126 | #include <unity/scopes/QueryBase.h> |
2127 | #include <unity/scopes/ActivationQueryBase.h> |
2128 | @@ -69,6 +70,8 @@ |
2129 | QSharedPointer<click::web::Client> client; |
2130 | QSharedPointer<click::Index> index; |
2131 | QSharedPointer<pay::Package> pay_package; |
2132 | + QSharedPointer<Ubuntu::DownloadManager::Manager> dm; |
2133 | + QSharedPointer<click::CredentialsService> sso; |
2134 | std::shared_ptr<click::DepartmentsDb> depts_db; |
2135 | |
2136 | std::string installApplication(unity::scopes::Result const& result); |
2137 | |
2138 | === modified file 'scope/clickstore/store-scope.cpp' |
2139 | --- scope/clickstore/store-scope.cpp 2015-11-24 18:23:23 +0000 |
2140 | +++ scope/clickstore/store-scope.cpp 2016-03-01 16:46:59 +0000 |
2141 | @@ -83,6 +83,9 @@ |
2142 | static const int zero = 0; |
2143 | auto emptyCb = [this]() |
2144 | { |
2145 | + sso.reset(new click::CredentialsService()); |
2146 | + client->setCredentialsService(sso); |
2147 | + dm.reset(Ubuntu::DownloadManager::Manager::createSessionManager()); |
2148 | }; |
2149 | |
2150 | qt::core::world::build_and_run(zero, nullptr, emptyCb); |
2151 | @@ -103,7 +106,7 @@ |
2152 | const unity::scopes::ActionMetadata& metadata) { |
2153 | qDebug() << "Scope::preview() called."; |
2154 | auto preview = new click::Preview(result, metadata); |
2155 | - preview->choose_strategy(client, nam, pay_package, depts_db); |
2156 | + preview->choose_strategy(client, pay_package, dm, depts_db); |
2157 | return unity::scopes::PreviewQueryBase::UPtr{preview}; |
2158 | } |
2159 | |
2160 | |
2161 | === modified file 'scope/clickstore/store-scope.h' |
2162 | --- scope/clickstore/store-scope.h 2015-11-24 18:23:23 +0000 |
2163 | +++ scope/clickstore/store-scope.h 2016-03-01 16:46:59 +0000 |
2164 | @@ -36,6 +36,7 @@ |
2165 | #include <click/network_access_manager.h> |
2166 | #include <click/webclient.h> |
2167 | |
2168 | +#include <ubuntu/download_manager/manager.h> |
2169 | #include <unity/scopes/ScopeBase.h> |
2170 | #include <unity/scopes/QueryBase.h> |
2171 | #include <unity/scopes/ActivationQueryBase.h> |
2172 | @@ -72,6 +73,8 @@ |
2173 | QSharedPointer<click::web::Client> client; |
2174 | QSharedPointer<click::Index> index; |
2175 | QSharedPointer<pay::Package> pay_package; |
2176 | + QSharedPointer<Ubuntu::DownloadManager::Manager> dm; |
2177 | + QSharedPointer<click::CredentialsService> sso; |
2178 | std::shared_ptr<click::DepartmentLookup> depts; |
2179 | std::shared_ptr<click::HighlightList> highlights; |
2180 | std::shared_ptr<click::DepartmentsDb> depts_db; |
2181 | |
2182 | === modified file 'scope/tests/CMakeLists.txt' |
2183 | --- scope/tests/CMakeLists.txt 2015-11-24 18:23:23 +0000 |
2184 | +++ scope/tests/CMakeLists.txt 2016-03-01 16:46:59 +0000 |
2185 | @@ -105,6 +105,5 @@ |
2186 | ) |
2187 | |
2188 | |
2189 | -add_subdirectory(download_manager_tool) |
2190 | add_subdirectory(click_interface_tool) |
2191 | add_subdirectory(fake_launcher) |
2192 | |
2193 | === removed directory 'scope/tests/download_manager_tool' |
2194 | === removed file 'scope/tests/download_manager_tool/CMakeLists.txt' |
2195 | --- scope/tests/download_manager_tool/CMakeLists.txt 2015-05-20 19:58:45 +0000 |
2196 | +++ scope/tests/download_manager_tool/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
2197 | @@ -1,14 +0,0 @@ |
2198 | -set(DOWNLOAD_MANAGER_TOOL_TARGET download_manager_tool) |
2199 | - |
2200 | -include_directories ( |
2201 | - ${CMAKE_SOURCE_DIR}/scope/click |
2202 | -) |
2203 | - |
2204 | -add_executable (${DOWNLOAD_MANAGER_TOOL_TARGET} |
2205 | - download_manager_tool.cpp |
2206 | - download_manager_tool.h |
2207 | -) |
2208 | - |
2209 | -target_link_libraries (${DOWNLOAD_MANAGER_TOOL_TARGET} |
2210 | - ${STORE_LIB_UNVERSIONED} |
2211 | -) |
2212 | |
2213 | === removed file 'scope/tests/download_manager_tool/download_manager_tool.cpp' |
2214 | --- scope/tests/download_manager_tool/download_manager_tool.cpp 2014-08-11 18:30:00 +0000 |
2215 | +++ scope/tests/download_manager_tool/download_manager_tool.cpp 1970-01-01 00:00:00 +0000 |
2216 | @@ -1,123 +0,0 @@ |
2217 | -/* |
2218 | - * Copyright (C) 2014 Canonical Ltd. |
2219 | - * |
2220 | - * This program is free software: you can redistribute it and/or modify it |
2221 | - * under the terms of the GNU General Public License version 3, as published |
2222 | - * by the Free Software Foundation. |
2223 | - * |
2224 | - * This program is distributed in the hope that it will be useful, but |
2225 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
2226 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2227 | - * PURPOSE. See the GNU General Public License for more details. |
2228 | - * |
2229 | - * You should have received a copy of the GNU General Public License along |
2230 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
2231 | - * |
2232 | - * In addition, as a special exception, the copyright holders give |
2233 | - * permission to link the code of portions of this program with the |
2234 | - * OpenSSL library under certain conditions as described in each |
2235 | - * individual source file, and distribute linked combinations |
2236 | - * including the two. |
2237 | - * You must obey the GNU General Public License in all respects |
2238 | - * for all of the code used other than OpenSSL. If you modify |
2239 | - * file(s) with this exception, you may extend this exception to your |
2240 | - * version of the file(s), but you are not obligated to do so. If you |
2241 | - * do not wish to do so, delete this exception statement from your |
2242 | - * version. If you delete this exception statement from all source |
2243 | - * files in the program, then also delete it here. |
2244 | - */ |
2245 | - |
2246 | -#include <QCoreApplication> |
2247 | -#include <QDebug> |
2248 | -#include <QString> |
2249 | -#include <QTimer> |
2250 | -#include <QTextStream> |
2251 | - |
2252 | -#include <iostream> |
2253 | - |
2254 | -#include <boost/optional.hpp> |
2255 | - |
2256 | -#include <download_manager_tool.h> |
2257 | - |
2258 | -DownloadManagerTool::DownloadManagerTool(QObject *parent): |
2259 | - QObject(parent) |
2260 | -{ |
2261 | - _dm = new click::DownloadManager(QSharedPointer<click::network::AccessManager>(new click::network::AccessManager()), |
2262 | - QSharedPointer<click::CredentialsService>(new click::CredentialsService()), |
2263 | - QSharedPointer<Ubuntu::DownloadManager::Manager>( |
2264 | - Ubuntu::DownloadManager::Manager::createSessionManager())); |
2265 | -} |
2266 | - |
2267 | -void DownloadManagerTool::handleResponse(QString response) |
2268 | -{ |
2269 | - QTextStream(stdout) << "DONE: response is " << response << "\n"; |
2270 | - emit finished(); |
2271 | -} |
2272 | - |
2273 | -void DownloadManagerTool::fetchClickToken(QString url, QString sha512) |
2274 | -{ |
2275 | - QObject::connect(_dm, &click::DownloadManager::clickTokenFetched, |
2276 | - this, &DownloadManagerTool::handleResponse); |
2277 | - QObject::connect(_dm, &click::DownloadManager::clickTokenFetchError, |
2278 | - this, &DownloadManagerTool::handleResponse); |
2279 | - _dm->fetchClickToken(url, sha512); |
2280 | -} |
2281 | - |
2282 | -void DownloadManagerTool::startDownload(QString url, QString sha512, QString appId) |
2283 | -{ |
2284 | - QObject::connect(_dm, &click::DownloadManager::downloadStarted, |
2285 | - this, &DownloadManagerTool::handleResponse); |
2286 | - QObject::connect(_dm, &click::DownloadManager::downloadError, |
2287 | - this, &DownloadManagerTool::handleResponse); |
2288 | - _dm->startDownload(url, sha512, appId); |
2289 | -} |
2290 | - |
2291 | -int main(int argc, char *argv[]) |
2292 | -{ |
2293 | - |
2294 | - QCoreApplication a(argc, argv); |
2295 | - DownloadManagerTool tool; |
2296 | - click::Downloader downloader(QSharedPointer<click::network::AccessManager>(new click::network::AccessManager())); |
2297 | - QTimer timer; |
2298 | - timer.setSingleShot(true); |
2299 | - |
2300 | - QObject::connect(&tool, SIGNAL(finished()), &a, SLOT(quit())); |
2301 | - |
2302 | - if (argc == 3) { |
2303 | - |
2304 | - QObject::connect(&timer, &QTimer::timeout, [&]() { |
2305 | - tool.fetchClickToken(QString(argv[1]), QString(argv[2])); |
2306 | - } ); |
2307 | - |
2308 | - } else if (argc == 4) { |
2309 | - |
2310 | - QObject::connect(&timer, &QTimer::timeout, [&]() { |
2311 | - downloader.startDownload(std::string(argv[1]), std::string(argv[2]), std::string(argv[3]), |
2312 | - [&a] (std::pair<std::string, click::InstallError> arg){ |
2313 | - auto error = arg.second; |
2314 | - if (error == click::InstallError::NoError) { |
2315 | - std::cout << " Success, got download ID:" << arg.first << std::endl; |
2316 | - } else { |
2317 | - std::cout << " Error:" << arg.first << std::endl; |
2318 | - } |
2319 | - a.quit(); |
2320 | - }); |
2321 | - |
2322 | - } ); |
2323 | - |
2324 | - } else { |
2325 | - QTextStream(stderr) << "Usages:\n" |
2326 | - << "download_manager_tool https://public.apps.ubuntu.com/download/<<rest of click package dl url>> sha512\n" |
2327 | - << "\t - when run with a valid U1 credential in the system, should print the click token to stdout.\n" |
2328 | - << "download_manager_tool url sha512 app_id\n" |
2329 | - << "\t - with a valid credential, should begin a download.\n"; |
2330 | - |
2331 | - return 1; |
2332 | - } |
2333 | - |
2334 | - timer.start(0); |
2335 | - |
2336 | - qInstallMessageHandler(0); |
2337 | - return a.exec(); |
2338 | -} |
2339 | - |
2340 | |
2341 | === removed file 'scope/tests/download_manager_tool/download_manager_tool.h' |
2342 | --- scope/tests/download_manager_tool/download_manager_tool.h 2014-08-11 18:30:00 +0000 |
2343 | +++ scope/tests/download_manager_tool/download_manager_tool.h 1970-01-01 00:00:00 +0000 |
2344 | @@ -1,59 +0,0 @@ |
2345 | -/* |
2346 | - * Copyright (C) 2014 Canonical Ltd. |
2347 | - * |
2348 | - * This program is free software: you can redistribute it and/or modify it |
2349 | - * under the terms of the GNU General Public License version 3, as published |
2350 | - * by the Free Software Foundation. |
2351 | - * |
2352 | - * This program is distributed in the hope that it will be useful, but |
2353 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
2354 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2355 | - * PURPOSE. See the GNU General Public License for more details. |
2356 | - * |
2357 | - * You should have received a copy of the GNU General Public License along |
2358 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
2359 | - * |
2360 | - * In addition, as a special exception, the copyright holders give |
2361 | - * permission to link the code of portions of this program with the |
2362 | - * OpenSSL library under certain conditions as described in each |
2363 | - * individual source file, and distribute linked combinations |
2364 | - * including the two. |
2365 | - * You must obey the GNU General Public License in all respects |
2366 | - * for all of the code used other than OpenSSL. If you modify |
2367 | - * file(s) with this exception, you may extend this exception to your |
2368 | - * version of the file(s), but you are not obligated to do so. If you |
2369 | - * do not wish to do so, delete this exception statement from your |
2370 | - * version. If you delete this exception statement from all source |
2371 | - * files in the program, then also delete it here. |
2372 | - */ |
2373 | - |
2374 | -#ifndef _DOWNLOAD_MANAGER_TOOL_H_ |
2375 | -#define _DOWNLOAD_MANAGER_TOOL_H_ |
2376 | - |
2377 | -#include <QString> |
2378 | -#include <click/download-manager.h> |
2379 | - |
2380 | -class DownloadManagerTool : public QObject { |
2381 | - Q_OBJECT |
2382 | - |
2383 | -public: |
2384 | - explicit DownloadManagerTool(QObject *parent=0); |
2385 | - |
2386 | -public slots: |
2387 | - void fetchClickToken(QString url, QString sha512); |
2388 | - void startDownload(QString url, QString sha512, QString appId); |
2389 | - |
2390 | -private slots: |
2391 | - void handleResponse(QString response); |
2392 | - |
2393 | -signals: |
2394 | - void finished(); |
2395 | - |
2396 | -private: |
2397 | - click::DownloadManager *_dm; |
2398 | - |
2399 | -}; |
2400 | - |
2401 | -#endif /* _DOWNLOAD_MANAGER_TOOL_H_ */ |
2402 | - |
2403 | - |