Merge lp:~dobey/unity-scope-click/no-more-click into lp:unity-scope-click

Proposed by dobey
Status: Merged
Approved by: dobey
Approved revision: 509
Merged at revision: 510
Proposed branch: lp:~dobey/unity-scope-click/no-more-click
Merge into: lp:unity-scope-click
Diff against target: 3453 lines (+11/-2854)
28 files modified
CMakeLists.txt (+0/-7)
bin/CMakeLists.txt (+0/-1)
bin/install-helper (+0/-77)
debian/control (+0/-9)
debian/unity-scope-click.install (+0/-1)
libclickscope/click/CMakeLists.txt (+0/-9)
libclickscope/click/download-manager.cpp (+0/-177)
libclickscope/click/download-manager.h (+0/-87)
libclickscope/click/index.cpp (+0/-43)
libclickscope/click/interface.cpp (+0/-90)
libclickscope/click/interface.h (+0/-4)
libclickscope/click/preview.cpp (+8/-610)
libclickscope/click/preview.h (+0/-122)
libclickscope/click/reviews.cpp (+0/-245)
libclickscope/click/reviews.h (+0/-95)
libclickscope/click/scope_activation.cpp (+0/-40)
libclickscope/click/scope_activation.h (+0/-7)
libclickscope/tests/CMakeLists.txt (+0/-5)
libclickscope/tests/mock_ubuntu_download_manager.h (+0/-140)
libclickscope/tests/test_bootstrap.cpp (+0/-1)
libclickscope/tests/test_download_manager.cpp (+0/-220)
libclickscope/tests/test_index.cpp (+0/-12)
libclickscope/tests/test_interface.cpp (+0/-74)
libclickscope/tests/test_preview.cpp (+0/-181)
libclickscope/tests/test_reviews.cpp (+0/-487)
scope/clickapps/apps-scope.cpp (+3/-42)
scope/clickapps/apps-scope.h (+0/-2)
scope/tests/test_apps_scope.cpp (+0/-66)
To merge this branch: bzr merge lp:~dobey/unity-scope-click/no-more-click
Reviewer Review Type Date Requested Status
Charles Kerr (community) Approve
unity-api-1-bot continuous-integration Approve
Review via email: mp+312754@code.launchpad.net

Commit message

Remove deps on ubuntu-download-manager and libclick.
Remove download-manager, installing, uninstalling, and reviews code.

To post a comment you must log in.
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:507
https://jenkins.canonical.com/unity-api-1/job/lp-unity-scope-click-ci/136/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1262
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1269
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1052
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1052/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/1052
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/1052/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1052
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1052/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/1052
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/1052/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/1052
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/1052/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/1052
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/1052/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-unity-scope-click-ci/136/rebuild

review: Approve (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:508
https://jenkins.canonical.com/unity-api-1/job/lp-unity-scope-click-ci/138/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/1312
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/1319
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1096
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/1096/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/1096
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=zesty/1096/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1096
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/1096/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/1096
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=zesty/1096/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/1096
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/1096/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/1096
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=zesty/1096/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-unity-scope-click-ci/138/rebuild

review: Approve (continuous-integration)
Revision history for this message
Charles Kerr (charlesk) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2016-12-02 18:37:59 +0000
+++ CMakeLists.txt 2017-01-10 16:06:37 +0000
@@ -26,9 +26,6 @@
26pkg_check_modules(UAL REQUIRED ubuntu-app-launch-2>=0.9 gobject-2.0)26pkg_check_modules(UAL REQUIRED ubuntu-app-launch-2>=0.9 gobject-2.0)
27add_definitions(${UAL_CFLAGS} ${UAL_CFLAGS_OTHER})27add_definitions(${UAL_CFLAGS} ${UAL_CFLAGS_OTHER})
2828
29pkg_check_modules(CLICK REQUIRED click-0.4)
30add_definitions(${CLICK_CFLAGS} ${CLICK_CFLAGS_OTHER})
31
32pkg_check_modules(UNITY_SCOPES REQUIRED libunity-scopes>=0.6.7 libunity-api>=0.1.3)29pkg_check_modules(UNITY_SCOPES REQUIRED libunity-scopes>=0.6.7 libunity-api>=0.1.3)
33add_definitions(${UNITY_SCOPES_CFLAGS} ${UNITY_SCOPES_CFLAGS_OTHER})30add_definitions(${UNITY_SCOPES_CFLAGS} ${UNITY_SCOPES_CFLAGS_OTHER})
3431
@@ -38,9 +35,6 @@
38pkg_check_modules(UBUNTUONE REQUIRED ubuntuoneauth-2.0>=15.10)35pkg_check_modules(UBUNTUONE REQUIRED ubuntuoneauth-2.0>=15.10)
39add_definitions(${UBUNTUONE_CFLAGS} ${UBUNTUONE_CFLAGS_OTHER})36add_definitions(${UBUNTUONE_CFLAGS} ${UBUNTUONE_CFLAGS_OTHER})
4037
41pkg_check_modules(UBUNTU_DOWNLOAD_MANAGER_CLIENT REQUIRED ubuntu-download-manager-client)
42pkg_check_modules(UBUNTU_DOWNLOAD_MANAGER_COMMON REQUIRED ubuntu-download-manager-common)
43
44SET (SCOPE_LIB_VERSION 0.2.0)38SET (SCOPE_LIB_VERSION 0.2.0)
45SET (SCOPE_LIB_SOVERSION 0)39SET (SCOPE_LIB_SOVERSION 0)
46SET (SCOPE_LIB_API_VERSION 2.0)40SET (SCOPE_LIB_API_VERSION 2.0)
@@ -50,7 +44,6 @@
5044
51# Add our own subdirectories.45# Add our own subdirectories.
52add_subdirectory(tests)46add_subdirectory(tests)
53add_subdirectory(bin)
54add_subdirectory(libclickscope)47add_subdirectory(libclickscope)
55add_subdirectory(scope)48add_subdirectory(scope)
56add_subdirectory(data)49add_subdirectory(data)
5750
=== removed directory 'bin'
=== removed file 'bin/CMakeLists.txt'
--- bin/CMakeLists.txt 2016-10-25 13:12:57 +0000
+++ bin/CMakeLists.txt 1970-01-01 00:00:00 +0000
@@ -1,1 +0,0 @@
1install(PROGRAMS install-helper DESTINATION lib/unity-scope-click/)
20
=== removed file 'bin/install-helper'
--- bin/install-helper 2014-06-20 05:09:01 +0000
+++ bin/install-helper 1970-01-01 00:00:00 +0000
@@ -1,77 +0,0 @@
1#!/bin/bash
2#
3# Copyright (C) 2014 Canonical Ltd.
4#
5# This program is free software: you can redistribute it and/or modify it
6# under the terms of the GNU General Public License version 3, as published
7# by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful, but
10# WITHOUT ANY WARRANTY; without even the implied warranties of
11# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12# PURPOSE. See the GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along
15# with this program. If not, see <http://www.gnu.org/licenses/>.
16#
17# In addition, as a special exception, the copyright holders give
18# permission to link the code of portions of this program with the
19# OpenSSL library under certain conditions as described in each
20# individual source file, and distribute linked combinations
21# including the two.
22# You must obey the GNU General Public License in all respects
23# for all of the code used other than OpenSSL. If you modify
24# file(s) with this exception, you may extend this exception to your
25# version of the file(s), but you are not obligated to do so. If you
26# do not wish to do so, delete this exception statement from your
27# version. If you delete this exception statement from all source
28# files in the program, then also delete it here.
29#
30
31FILE_NAME="$1"
32PACKAGE_NAME="$2"
33
34SCOPES_OBJECTPATH=/com/canonical/unity/scopes
35SCOPES_INTERFACE=com.canonical.unity.scopes
36SCOPES_METHOD=InvalidateResults
37
38LAUNCHER_BUS=com.ubuntu.unity.launcher
39LAUNCHER_OBJECTPATH=/com/ubuntu/unity/launcher/installations
40LAUNCHER_INTERFACE=com.ubuntu.unity.launcher.Installations
41LAUNCHER_METHOD=completeInstallation
42
43function invalidate-scope {
44 SCOPE_ID=$1
45 dbus-send $SCOPES_OBJECTPATH $SCOPES_INTERFACE.$SCOPES_METHOD string:$SCOPE_ID
46}
47
48function install-package {
49 FILE_NAME="$1"
50 pkcon -p install-local "$FILE_NAME"
51}
52
53function app_id-from-package_name {
54 PACKAGE_NAME=$1
55 IFS=_
56 TRIPLET=($(ubuntu-app-triplet $PACKAGE_NAME))
57 unset IFS
58 echo ${TRIPLET[0]}_${TRIPLET[1]}_current-user-version
59}
60
61function complete-installation {
62 PACKAGE_NAME=$1
63 APP_ID=$2
64 dbus-send --dest=$LAUNCHER_BUS --type=method_call $LAUNCHER_OBJECTPATH $LAUNCHER_INTERFACE.$LAUNCHER_METHOD string:$PACKAGE_NAME string:$APP_ID
65}
66
67if install-package "$FILE_NAME" ; then
68 invalidate-scope clickscope
69 invalidate-scope com.canonical.scopes.clickstore
70 APP_ID=$(app_id-from-package_name $PACKAGE_NAME)
71 complete-installation $PACKAGE_NAME $APP_ID
72else
73 PKCON_STATUS=$?
74 NO_APP_ID=""
75 complete-installation $PACKAGE_NAME $NO_APP_ID
76 exit $PKCON_STATUS
77fi
780
=== modified file 'debian/control'
--- debian/control 2016-12-21 15:27:35 +0000
+++ debian/control 2017-01-10 16:06:37 +0000
@@ -12,24 +12,19 @@
12 intltool,12 intltool,
13 lcov,13 lcov,
14 libboost-locale-dev,14 libboost-locale-dev,
15 libclick-0.4-dev,
16 libglib2.0-dev (>= 2.32),15 libglib2.0-dev (>= 2.32),
17 libjsoncpp-dev,16 libjsoncpp-dev,
18 libubuntu-app-launch2-dev (>= 0.9),17 libubuntu-app-launch2-dev (>= 0.9),
19 libubuntu-download-manager-client-dev (>= 0.3+14.10.20140430-0ubuntu1),
20 libubuntu-download-manager-common-dev (>= 0.3+14.10.20140430-0ubuntu1),
21 libubuntuoneauth-2.0-dev (>= 15.10),18 libubuntuoneauth-2.0-dev (>= 15.10),
22 libunity-api-dev (>= 7.80.7),19 libunity-api-dev (>= 7.80.7),
23 libunity-scopes-dev (>= 0.6.7~),20 libunity-scopes-dev (>= 0.6.7~),
24 libgsettings-qt-dev,21 libgsettings-qt-dev,
25 ubuntu-sdk-libs,
26 pkg-config,22 pkg-config,
27 python3-all:native,23 python3-all:native,
28 python3-fixtures,24 python3-fixtures,
29 python3-scope-harness (>= 0.5.8),25 python3-scope-harness (>= 0.5.8),
30 python3-testtools,26 python3-testtools,
31 xvfb,27 xvfb,
32 ubuntu-download-manager,
33Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>28Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
34Standards-Version: 3.9.529Standards-Version: 3.9.5
35Homepage: https://launchpad.net/unity-scope-click30Homepage: https://launchpad.net/unity-scope-click
@@ -42,10 +37,6 @@
42Depends: account-plugin-ubuntuone,37Depends: account-plugin-ubuntuone,
43 libglib2.0-bin,38 libglib2.0-bin,
44 libsqlite3-0 (>= 3.8.5),39 libsqlite3-0 (>= 3.8.5),
45 packagekit,
46 packagekit-tools,
47 ubuntu-app-launch-tools,
48 ubuntu-download-manager,
49 ${misc:Depends},40 ${misc:Depends},
50 ${shlibs:Depends},41 ${shlibs:Depends},
51Breaks: unity (<< 7.0),42Breaks: unity (<< 7.0),
5243
=== modified file 'debian/unity-scope-click.install'
--- debian/unity-scope-click.install 2016-11-04 20:17:19 +0000
+++ debian/unity-scope-click.install 2017-01-10 16:06:37 +0000
@@ -1,5 +1,4 @@
1usr/lib/*/unity-scopes/*1usr/lib/*/unity-scopes/*
2usr/lib/unity-scope-click/*
3usr/share/unity/scopes/clickapps/*.jpg2usr/share/unity/scopes/clickapps/*.jpg
4usr/share/unity/scopes/clickapps/*.png3usr/share/unity/scopes/clickapps/*.png
5usr/share/unity/scopes/clickapps/*.svg4usr/share/unity/scopes/clickapps/*.svg
65
=== modified file 'libclickscope/click/CMakeLists.txt'
--- libclickscope/click/CMakeLists.txt 2016-10-24 21:26:23 +0000
+++ libclickscope/click/CMakeLists.txt 2017-01-10 16:06:37 +0000
@@ -8,13 +8,11 @@
8add_definitions(8add_definitions(
9 -DGETTEXT_PACKAGE=\"${PROJECT_NAME}\"9 -DGETTEXT_PACKAGE=\"${PROJECT_NAME}\"
10 -DGETTEXT_LOCALEDIR=\"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALEDIR}\"10 -DGETTEXT_LOCALEDIR=\"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALEDIR}\"
11 -DCLICK_INSTALL_HELPER=\"${CMAKE_INSTALL_PREFIX}/lib/unity-scope-click/install-helper\"
12 ${GSETTINGS_QT_CFLAGS} ${GSETTINGS_QT_OTHER}11 ${GSETTINGS_QT_CFLAGS} ${GSETTINGS_QT_OTHER}
13)12)
1413
15add_library(${SCOPE_LIB_NAME} STATIC14add_library(${SCOPE_LIB_NAME} STATIC
16 configuration.cpp15 configuration.cpp
17 download-manager.cpp
18 department-lookup.cpp16 department-lookup.cpp
19 departments.cpp17 departments.cpp
20 departments-db.cpp18 departments-db.cpp
@@ -25,7 +23,6 @@
25 network_access_manager.cpp23 network_access_manager.cpp
26 package.cpp24 package.cpp
27 preview.cpp25 preview.cpp
28 reviews.cpp
29 qtbridge.cpp26 qtbridge.cpp
30 scope_activation.cpp27 scope_activation.cpp
31 smartconnect.cpp28 smartconnect.cpp
@@ -38,22 +35,16 @@
3835
39include_directories(36include_directories(
40 ${JSON_CPP_INCLUDE_DIRS}37 ${JSON_CPP_INCLUDE_DIRS}
41 ${LIBPAY_INCLUDE_DIRS}
42 ${GSETTINGS_QT_INCLUDE_DIRS}38 ${GSETTINGS_QT_INCLUDE_DIRS}
43 ${UAL_INCLUDE_DIRS}39 ${UAL_INCLUDE_DIRS}
44 ${CLICK_INCLUDE_DIRS}
45 ${CMAKE_SOURCE_DIR}/libclickscope40 ${CMAKE_SOURCE_DIR}/libclickscope
46)41)
4742
48target_link_libraries (${SCOPE_LIB_NAME}43target_link_libraries (${SCOPE_LIB_NAME}
49 ${JSON_CPP_LDFLAGS}44 ${JSON_CPP_LDFLAGS}
50 ${LIBPAY_LDFLAGS}
51 ${UNITY_SCOPES_LDFLAGS}45 ${UNITY_SCOPES_LDFLAGS}
52 ${UBUNTUONE_LDFLAGS}46 ${UBUNTUONE_LDFLAGS}
53 ${UBUNTU_DOWNLOAD_MANAGER_CLIENT_LDFLAGS}
54 ${UBUNTU_DOWNLOAD_MANAGER_COMMON_LDFLAGS}
55 ${GSETTINGS_QT_LIBRARIES}47 ${GSETTINGS_QT_LIBRARIES}
56 ${UAL_LDFLAGS}48 ${UAL_LDFLAGS}
57 ${CLICK_LDFLAGS}
58 -lboost_locale49 -lboost_locale
59)50)
6051
=== removed file 'libclickscope/click/download-manager.cpp'
--- libclickscope/click/download-manager.cpp 2016-05-10 13:42:12 +0000
+++ libclickscope/click/download-manager.cpp 1970-01-01 00:00:00 +0000
@@ -1,177 +0,0 @@
1/*
2 * Copyright (C) 2014-2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include "download-manager.h"
31
32#include <QDebug>
33#include <QObject>
34#include <QString>
35#include <QStringBuilder>
36#include <QTimer>
37
38#include <click/qtbridge.h>
39
40namespace u1 = UbuntuOne;
41#include <click/ubuntuone_credentials.h>
42#include <token.h>
43
44namespace udm = Ubuntu::DownloadManager;
45#include <ubuntu/download_manager/download_struct.h>
46#include <ubuntu/download_manager/downloads_list.h>
47#include <ubuntu/download_manager/download.h>
48#include <ubuntu/download_manager/error.h>
49
50namespace click
51{
52
53static const QString DOWNLOAD_APP_ID_KEY = "app_id";
54static const QString DOWNLOAD_COMMAND_KEY = "post-download-command";
55
56static const QString DOWNLOAD_COMMAND = CLICK_INSTALL_HELPER;
57
58static const QString DOWNLOAD_MANAGER_SHA512 = "sha512";
59
60const QByteArray& CLICK_TOKEN_HEADER()
61{
62 static const QByteArray result("X-Click-Token");
63 return result;
64}
65
66DownloadManager::DownloadManager(const QSharedPointer<click::web::Client>& client,
67 const QSharedPointer<udm::Manager>& manager) :
68 client(client),
69 dm(manager)
70{
71}
72
73DownloadManager::~DownloadManager()
74{
75}
76
77void DownloadManager::get_progress(const std::string& package_name,
78 const std::function<void (std::string)>& callback)
79{
80 dm->getAllDownloadsWithMetadata(DOWNLOAD_APP_ID_KEY,
81 QString::fromStdString(package_name),
82 [callback, package_name](const QString& /*key*/, const QString& /*value*/, DownloadsList* downloads_list){
83 // got downloads matching metadata
84 std::string object_path;
85 auto downloads = downloads_list->downloads();
86 if (downloads.size() > 0) {
87 auto download = downloads.at(0);
88 object_path = download->id().toStdString();
89 }
90 qDebug() << "Found object path" << QString::fromStdString(object_path)
91 << "for package" << QString::fromStdString(package_name);
92 if (downloads.size() > 1) {
93 qWarning() << "More than one download with the same object path";
94 }
95 callback(object_path);
96 }, [callback, package_name](const QString& /*key*/, const QString& /*value*/, DownloadsList* /*downloads_list*/){
97 // no downloads found
98 qDebug() << "No object path found for package" << QString::fromStdString(package_name);
99 callback("");
100 });
101}
102
103click::web::Cancellable DownloadManager::start(const std::string& url,
104 const std::string& download_sha512,
105 const std::string& package_name,
106 const std::function<void (std::string, Error)>& callback)
107{
108 QSharedPointer<click::web::Response> response = client->call
109 (url, "HEAD", true);
110
111 QObject::connect(response.data(), &click::web::Response::finished,
112 [this, callback, url, download_sha512, package_name,
113 response](QString) {
114 auto status = response->get_status_code();
115 if (status == 200) {
116 auto clickToken = response->get_header(CLICK_TOKEN_HEADER().data());
117 qDebug() << "Received click token:" << clickToken.c_str();
118 QVariantMap metadata;
119
120 QVariant commandline = QVariant(QStringList() << DOWNLOAD_COMMAND << "$file" << package_name.c_str());
121 metadata[DOWNLOAD_COMMAND_KEY] = commandline;
122 metadata[DOWNLOAD_APP_ID_KEY] = package_name.c_str();
123 metadata["package_name"] = package_name.c_str();
124
125 QMap<QString, QString> headers;
126 headers[CLICK_TOKEN_HEADER()] = clickToken.c_str();
127
128 udm::DownloadStruct downloadStruct(url.c_str(),
129 download_sha512.c_str(),
130 DOWNLOAD_MANAGER_SHA512,
131 metadata,
132 headers);
133
134 dm->createDownload(downloadStruct,
135 [callback](Download* download) {
136 if (download->isError()) {
137 auto error = download->error()->errorString().toUtf8().data();
138 qDebug() << "Received error from ubuntu-download-manager:" << error;
139 callback(error, Error::DownloadInstallError);
140 } else {
141 download->start();
142 callback(download->id().toUtf8().data(), Error::NoError);
143 }
144 },
145 [callback](Download* download) {
146 callback(download->error()->errorString().toUtf8().data(),
147 Error::DownloadInstallError);
148 });
149 } else {
150 std::string error{"Unhandled HTTP response code: "};
151 error += status;
152 callback(error, Error::DownloadInstallError);
153 }
154 });
155 QObject::connect(response.data(), &click::web::Response::error,
156 [this, callback, package_name](QString error, int error_code) {
157 qWarning() << QStringLiteral("Network error (%1) fetching click token for:").arg(error_code) << package_name.c_str();
158 switch(error_code) {
159 case 401:
160 case 403:
161 client->invalidateCredentials();
162 callback(error.toUtf8().data(), Error::CredentialsError);
163 break;
164 default:
165 callback(error.toUtf8().data(), Error::DownloadInstallError);
166 }
167 });
168
169 return click::web::Cancellable(response);
170}
171
172void DownloadManager::setCredentialsService(const QSharedPointer<click::CredentialsService>& credentialsService)
173{
174 sso = credentialsService;
175}
176
177} // namespace click
1780
=== removed file 'libclickscope/click/download-manager.h'
--- libclickscope/click/download-manager.h 2016-02-26 18:51:22 +0000
+++ libclickscope/click/download-manager.h 1970-01-01 00:00:00 +0000
@@ -1,87 +0,0 @@
1/*
2 * Copyright (C) 2014-2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#ifndef CLICK_DOWNLOAD_MANAGER_H
31#define CLICK_DOWNLOAD_MANAGER_H
32
33#include <QDebug>
34#include <QNetworkReply>
35#include <QObject>
36#include <QString>
37
38#include <click/ubuntuone_credentials.h>
39#include <click/webclient.h>
40
41#include <ubuntu/download_manager/manager.h>
42
43using Ubuntu::DownloadManager::Download;
44
45namespace UbuntuOne
46{
47class Token;
48}
49
50namespace click
51{
52// The dbus-send command to refresh the search results in the dash.
53static const QString REFRESH_SCOPE_COMMAND = QStringLiteral("dbus-send /com/canonical/unity/scopes com.canonical.unity.scopes.InvalidateResults string:%1");
54static const QString APPS_SCOPE_ID = QStringLiteral("clickscope");
55static const QString STORE_SCOPE_ID = QStringLiteral("com.canonical.scopes.clickstore");
56
57const QByteArray& CLICK_TOKEN_HEADER();
58
59
60class DownloadManager
61{
62public:
63 enum class Error {NoError, CredentialsError, DownloadInstallError};
64
65 DownloadManager(const QSharedPointer<click::web::Client>& client,
66 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager);
67 virtual ~DownloadManager();
68
69 virtual void get_progress(const std::string& package_name,
70 const std::function<void (std::string)>& callback);
71 virtual click::web::Cancellable start(const std::string& url,
72 const std::string& download_sha512,
73 const std::string& package_name,
74 const std::function<void (std::string,
75 Error)>& callback);
76
77 virtual void setCredentialsService(const QSharedPointer<click::CredentialsService>& credentialsService);
78
79protected:
80 QSharedPointer<click::web::Client> client;
81 QSharedPointer<Ubuntu::DownloadManager::Manager> dm;
82 QSharedPointer<click::CredentialsService> sso;
83};
84
85}
86
87#endif /* CLICK_DOWNLOAD_MANAGER_H */
880
=== modified file 'libclickscope/click/index.cpp'
--- libclickscope/click/index.cpp 2016-04-26 10:56:47 +0000
+++ libclickscope/click/index.cpp 2017-01-10 16:06:37 +0000
@@ -36,7 +36,6 @@
3636
37#include <click/smartconnect.h>37#include <click/smartconnect.h>
3838
39#include <click/download-manager.h>
40#include "index.h"39#include "index.h"
41#include "interface.h"40#include "interface.h"
42#include "application.h"41#include "application.h"
@@ -46,48 +45,6 @@
46namespace click45namespace click
47{46{
4847
49void PackageManager::uninstall(const Package& package,
50 std::function<void(int, std::string)> callback)
51{
52 std::string package_id = package.name + ";" + package.version + ";all;local:click";
53 std::string command = "pkcon -p remove " + package_id;
54 execute_uninstall_command(command, callback);
55}
56
57void PackageManager::execute_uninstall_command(const std::string& command,
58 std::function<void(int, std::string)> callback)
59{
60 QSharedPointer<QProcess> process(new QProcess());
61
62 typedef void(QProcess::*QProcessFinished)(int, QProcess::ExitStatus);
63 typedef void(QProcess::*QProcessError)(QProcess::ProcessError);
64 QObject::connect(process.data(),
65 static_cast<QProcessFinished>(&QProcess::finished),
66 [process, callback](int code, QProcess::ExitStatus status) {
67 Q_UNUSED(status);
68 qDebug() << "command finished with exit code:" << code;
69 callback(code, process.data()->readAllStandardError().data());
70 if (code == 0) {
71 invalidate_results(APPS_SCOPE_ID.toUtf8().data());
72 invalidate_results(STORE_SCOPE_ID.toUtf8().data());
73 }
74 } );
75 QObject::connect(process.data(),
76 static_cast<QProcessError>(&QProcess::error),
77 [process, callback](QProcess::ProcessError error) {
78 qCritical() << "error running command:" << error;
79 callback(-255 + error, process.data()->readAllStandardError().data());
80 } );
81 qDebug() << "Running command:" << command.c_str();
82 process.data()->start(command.c_str());
83}
84
85void PackageManager::invalidate_results(const std::string& scope_id)
86{
87 QProcess::execute(REFRESH_SCOPE_COMMAND.arg(scope_id.c_str()));
88}
89
90
91Index::Index(const QSharedPointer<click::web::Client>& client,48Index::Index(const QSharedPointer<click::web::Client>& client,
92 const QSharedPointer<Configuration> configuration) :49 const QSharedPointer<Configuration> configuration) :
93 client(client), configuration(configuration)50 client(client), configuration(configuration)
9451
=== modified file 'libclickscope/click/interface.cpp'
--- libclickscope/click/interface.cpp 2016-10-04 17:35:15 +0000
+++ libclickscope/click/interface.cpp 2017-01-10 16:06:37 +0000
@@ -27,8 +27,6 @@
27 * files in the program, then also delete it here.27 * files in the program, then also delete it here.
28 */28 */
2929
30#include <click.h>
31
32#include "interface.h"30#include "interface.h"
3331
34#include <QDebug>32#include <QDebug>
@@ -343,39 +341,6 @@
343 return icon_id;341 return icon_id;
344}342}
345343
346Manifest manifest_from_json(const std::string& json)
347{
348 using namespace boost::property_tree;
349
350 std::istringstream is(json);
351
352 ptree pt;
353 read_json(is, pt);
354
355 Manifest manifest;
356
357 manifest.name = pt.get<std::string>("name");
358 manifest.version = pt.get<std::string>("version");
359 manifest.removable = pt.get<bool>("_removable");
360
361 BOOST_FOREACH(ptree::value_type &sv, pt.get_child("hooks"))
362 {
363 // FIXME: "primary app or scope" for a package is not defined,
364 // we just use the first one in the manifest:
365 auto app_name = sv.second.get("desktop", "");
366 if (manifest.first_app_name.empty() && !app_name.empty()) {
367 manifest.first_app_name = sv.first;
368 }
369 auto scope_id = sv.second.get("scope", "");
370 if (manifest.first_scope_id.empty() && !scope_id.empty()) {
371 manifest.first_scope_id = manifest.name + "_" + sv.first;
372 }
373 }
374 qDebug() << "adding manifest: " << manifest.name.c_str() << manifest.version.c_str() << manifest.first_app_name.c_str();
375
376 return manifest;
377}
378
379void Interface::get_installed_packages(std::function<void(PackageSet, InterfaceError)> callback)344void Interface::get_installed_packages(std::function<void(PackageSet, InterfaceError)> callback)
380{345{
381 PackageSet packages;346 PackageSet packages;
@@ -391,59 +356,4 @@
391 callback(packages, InterfaceError::NoError);356 callback(packages, InterfaceError::NoError);
392}357}
393358
394std::string Interface::get_manifest_json(const std::string &package) const
395{
396 GError* error = nullptr;
397
398 std::shared_ptr<ClickDB> clickdb{click_db_new(),
399 [](ClickDB* db){g_clear_object(&db);}};
400 click_db_read(clickdb.get(), nullptr, &error);
401 if (error != nullptr) {
402 qCritical() << "Error reading click DB:" << error->message;
403 g_error_free(error);
404 return "";
405 }
406
407 std::shared_ptr<ClickUser> clickuser{click_user_new_for_user(clickdb.get(),
408 nullptr,
409 &error),
410 [](ClickUser* cu){g_clear_object(&cu);}};
411 if (error != nullptr) {
412 qCritical() << "Error setting up click user:" << error->message;
413 g_error_free(error);
414 return "";
415 }
416
417 auto result = click_user_get_manifest_as_string(clickuser.get(),
418 package.c_str(),
419 &error);
420 if (error != nullptr) {
421 qCritical() << "Error getting manifest:" << error->message;
422 g_error_free(error);
423 return "";
424 }
425
426 std::string retval;
427 if (result != nullptr) {
428 retval = result;
429 g_free(result);
430 }
431 return retval;
432}
433
434void Interface::get_manifest_for_app(const std::string &app_id,
435 std::function<void(Manifest, InterfaceError)> callback)
436{
437 Manifest manifest;
438 InterfaceError error;
439 try {
440 manifest = manifest_from_json(get_manifest_json(app_id));
441 error = InterfaceError::NoError;
442 } catch (...) {
443 qWarning() << "Can't parse manifest for:" << QString::fromStdString(app_id);
444 error = InterfaceError::ParseError;
445 }
446 callback(manifest, error);
447}
448
449} // namespace click359} // namespace click
450360
=== modified file 'libclickscope/click/interface.h'
--- libclickscope/click/interface.h 2016-09-02 21:29:13 +0000
+++ libclickscope/click/interface.h 2017-01-10 16:06:37 +0000
@@ -77,8 +77,6 @@
77enum class InterfaceError {NoError, CallError, ParseError};77enum class InterfaceError {NoError, CallError, ParseError};
78typedef std::list<Manifest> ManifestList;78typedef std::list<Manifest> ManifestList;
7979
80Manifest manifest_from_json(const std::string& json);
81
82class Interface80class Interface
83{81{
84public:82public:
@@ -97,8 +95,6 @@
97 static bool is_icon_identifier(const std::string &icon_id);95 static bool is_icon_identifier(const std::string &icon_id);
98 static std::string add_theme_scheme(const std::string &filename);96 static std::string add_theme_scheme(const std::string &filename);
99 virtual void get_installed_packages(std::function<void(PackageSet, InterfaceError)> callback);97 virtual void get_installed_packages(std::function<void(PackageSet, InterfaceError)> callback);
100 virtual std::string get_manifest_json(const std::string &package) const;
101 virtual void get_manifest_for_app(const std::string &app_id, std::function<void(Manifest, InterfaceError)> callback);
102};98};
10399
104} // namespace click100} // namespace click
105101
=== modified file 'libclickscope/click/preview.cpp'
--- libclickscope/click/preview.cpp 2016-10-24 21:26:23 +0000
+++ libclickscope/click/preview.cpp 2017-01-10 16:06:37 +0000
@@ -31,7 +31,6 @@
31#include <click/interface.h>31#include <click/interface.h>
32#include "preview.h"32#include "preview.h"
33#include <click/qtbridge.h>33#include <click/qtbridge.h>
34#include <click/download-manager.h>
35#include <click/launcher.h>34#include <click/launcher.h>
36#include <click/dbus_constants.h>35#include <click/dbus_constants.h>
37#include <click/departments-db.h>36#include <click/departments-db.h>
@@ -172,76 +171,20 @@
172}171}
173172
174void Preview::choose_strategy(const QSharedPointer<web::Client> &client,173void Preview::choose_strategy(const QSharedPointer<web::Client> &client,
175 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager,
176 std::shared_ptr<click::DepartmentsDb> depts)174 std::shared_ptr<click::DepartmentsDb> depts)
177{175{
178 strategy.reset(build_strategy(result, metadata, client, manager, depts));176 strategy.reset(build_strategy(result, metadata, client, depts));
179}177}
180
181PreviewStrategy* Preview::build_installing(const std::string& download_url,
182 const std::string& download_sha512,
183 const unity::scopes::Result& result,
184 const QSharedPointer<click::web::Client>& client,
185 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager,
186 std::shared_ptr<click::DepartmentsDb> depts)
187{
188 return new InstallingPreview(download_url, download_sha512, result, client, manager, depts);
189}
190
191178
192PreviewStrategy* Preview::build_strategy(const unity::scopes::Result &result,179PreviewStrategy* Preview::build_strategy(const unity::scopes::Result &result,
193 const unity::scopes::ActionMetadata &metadata,180 const unity::scopes::ActionMetadata &metadata,
194 const QSharedPointer<web::Client> &client,181 const QSharedPointer<web::Client> &client,
195 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager,
196 std::shared_ptr<click::DepartmentsDb> depts)182 std::shared_ptr<click::DepartmentsDb> depts)
197{183{
198 if (metadata.scope_data().which() != scopes::Variant::Type::Null) {184 if (result.uri().find("scope://") == 0) {
199 auto metadict = metadata.scope_data().get_dict();185 return new InstalledScopePreview(result);
200
201 if (metadict.count(click::Preview::Actions::DOWNLOAD_FAILED) != 0) {
202 return new DownloadErrorPreview(result);
203 } else if (metadict.count(click::Preview::Actions::DOWNLOAD_COMPLETED) != 0 ||
204 metadict.count(click::Preview::Actions::SHOW_INSTALLED) != 0) {
205 qDebug() << "in Scope::preview(), metadata has download_completed="
206 << metadict.count(click::Preview::Actions::DOWNLOAD_COMPLETED)
207 << " and close_preview="
208 << metadict.count(click::Preview::Actions::SHOW_INSTALLED);
209
210 return new InstalledPreview(result, metadata, client, depts);
211 } else if (metadict.count("action_id") != 0 && metadict.count("download_url") != 0) {
212 std::string action_id = metadict["action_id"].get_string();
213 std::string download_url = metadict["download_url"].get_string();
214 std::string download_sha512 = metadict["download_sha512"].get_string();
215 if (action_id == click::Preview::Actions::INSTALL_CLICK) {
216 return build_installing(download_url, download_sha512, result, client, manager, depts);
217 } else {
218 qWarning() << "unexpected action id " << QString::fromStdString(action_id)
219 << " given with download_url" << QString::fromStdString(download_url);
220 return new UninstalledPreview(result, metadata, client, depts, manager);
221 }
222 } else if (metadict.count(click::Preview::Actions::UNINSTALL_CLICK) != 0) {
223 return new UninstallConfirmationPreview(result);
224 } else if (metadict.count(click::Preview::Actions::CONFIRM_UNINSTALL) != 0) {
225 return new UninstallingPreview(result, metadata, client, manager);
226 } else if (metadict.count(click::Preview::Actions::RATED) != 0) {
227 return new InstalledPreview(result, metadata, client, depts);
228 } else if (metadict.count(click::Preview::Actions::SHOW_UNINSTALLED) != 0) {
229 return new UninstalledPreview(result, metadata, client, depts, manager);
230 } else {
231 qWarning() << "preview() called with unexpected metadata. returning uninstalled preview";
232 return new UninstalledPreview(result, metadata, client, depts, manager);
233 }
234 } else {186 } else {
235 // metadata.scope_data() is Null, so we return an appropriate "default" preview:187 return new InstalledPreview(result, metadata, client, depts);
236 if (result.uri().find("scope://") == 0)
237 {
238 return new InstalledScopePreview(result);
239 }
240 if (result["installed"].get_bool() == true) {
241 return new InstalledPreview(result, metadata, client, depts);
242 } else {
243 return new UninstalledPreview(result, metadata, client, depts, manager);
244 }
245 }188 }
246189
247}190}
@@ -271,7 +214,6 @@
271 result(result),214 result(result),
272 client(client),215 client(client),
273 index(new click::Index(client)),216 index(new click::Index(client)),
274 reviews(new click::Reviews(client)),
275 oa_client("ubuntuone", "ubuntuone", "ubuntuone",217 oa_client("ubuntuone", "ubuntuone", "ubuntuone",
276 scopes::OnlineAccountClient::MainLoopSelect::CreateInternalMainLoop)218 scopes::OnlineAccountClient::MainLoopSelect::CreateInternalMainLoop)
277{219{
@@ -327,9 +269,6 @@
327void PreviewStrategy::cancelled()269void PreviewStrategy::cancelled()
328{270{
329 index_operation.cancel();271 index_operation.cancel();
330 reviews_operation.cancel();
331 submit_operation.cancel();
332 purchase_operation.cancel();
333}272}
334273
335scopes::PreviewWidget PreviewStrategy::build_other_metadata(const PackageDetails &details)274scopes::PreviewWidget PreviewStrategy::build_other_metadata(const PackageDetails &details)
@@ -396,8 +335,7 @@
396// return them from populateDetails and check them in the calling code335// return them from populateDetails and check them in the calling code
397// to decide whether to show error widgets. see bug LP: #1289541336// to decide whether to show error widgets. see bug LP: #1289541
398void PreviewStrategy::populateDetails(std::function<void(const click::PackageDetails& details)> details_callback,337void PreviewStrategy::populateDetails(std::function<void(const click::PackageDetails& details)> details_callback,
399 std::function<void(const click::ReviewList&,338 bool force_cache)
400 click::Reviews::Error)> reviews_callback, bool force_cache)
401{339{
402340
403 std::string app_name = get_string_maybe_null(result["name"]);341 std::string app_name = get_string_maybe_null(result["name"]);
@@ -410,15 +348,14 @@
410 details.description = get_string_maybe_null(result["description"]);348 details.description = get_string_maybe_null(result["description"]);
411 details.main_screenshot_url = get_string_maybe_null(result["main_screenshot"]);349 details.main_screenshot_url = get_string_maybe_null(result["main_screenshot"]);
412 details_callback(details);350 details_callback(details);
413 reviews_callback(click::ReviewList(), click::Reviews::Error::NoError);
414 } else {351 } else {
415 qDebug() << "in populateDetails(), app_name is:" << app_name.c_str();352 qDebug() << "in populateDetails(), app_name is:" << app_name.c_str();
416 // I think this should not be required when we switch the click::Index over353 // I think this should not be required when we switch the click::Index over
417 // to using the Qt bridge. With that, the qt dependency becomes an implementation detail354 // to using the Qt bridge. With that, the qt dependency becomes an implementation detail
418 // and code using it does not need to worry about threading/event loop topics.355 // and code using it does not need to worry about threading/event loop topics.
419 run_under_qt([this, details_callback, reviews_callback, app_name, force_cache]()356 run_under_qt([this, details_callback, app_name, force_cache]()
420 {357 {
421 index_operation = index->get_details(app_name, [this, app_name, details_callback, reviews_callback, force_cache](PackageDetails details, click::Index::Error error){358 index_operation = index->get_details(app_name, [this, app_name, details_callback, force_cache](PackageDetails details, click::Index::Error error){
422 if(error == click::Index::Error::NoError) {359 if(error == click::Index::Error::NoError) {
423 qDebug() << "Got details:" << app_name.c_str();360 qDebug() << "Got details:" << app_name.c_str();
424 details_callback(details);361 details_callback(details);
@@ -431,9 +368,6 @@
431 details.main_screenshot_url = get_string_maybe_null(result["main_screenshot"]);368 details.main_screenshot_url = get_string_maybe_null(result["main_screenshot"]);
432 details_callback(details);369 details_callback(details);
433 }370 }
434 reviews_operation = reviews->fetch_reviews(app_name,
435 reviews_callback,
436 force_cache);
437 }, force_cache);371 }, force_cache);
438 });372 });
439 }373 }
@@ -551,65 +485,6 @@
551 return widgets;485 return widgets;
552}486}
553487
554scopes::PreviewWidgetList PreviewStrategy::reviewsWidgets(const click::ReviewList& reviewlist)
555{
556 scopes::PreviewWidgetList widgets;
557
558 scopes::PreviewWidget rating("reviews", "reviews");
559 scopes::VariantBuilder builder;
560
561 if (reviewlist.size() > 0) {
562 scopes::PreviewWidget title("reviews_title", "text");
563 title.add_attribute_value("title", scopes::Variant(_("Reviews")));
564 widgets.push_back(title);
565
566 for (const auto& kv : reviewlist) {
567 builder.add_tuple({
568 {"rating", scopes::Variant(kv.rating)},
569 {"author", scopes::Variant(kv.reviewer_name)},
570 {"review", scopes::Variant(kv.review_text)}
571 });
572 }
573 rating.add_attribute_value("reviews", builder.end());
574 widgets.push_back(rating);
575 }
576
577 return widgets;
578}
579
580scopes::PreviewWidgetList PreviewStrategy::downloadErrorWidgets()
581{
582 return errorWidgets(scopes::Variant(_("Download Error")),
583 scopes::Variant(_("Download or install failed. Please try again.")),
584 scopes::Variant(click::Preview::Actions::SHOW_UNINSTALLED),
585 scopes::Variant(_("Close")));
586}
587
588scopes::PreviewWidgetList PreviewStrategy::loginErrorWidgets(const std::string& download_url, const std::string& download_sha512)
589{
590 auto widgets = errorWidgets(scopes::Variant(_("Login Error")),
591 scopes::Variant(_("Please log in to your Ubuntu One account.")),
592 scopes::Variant(click::Preview::Actions::INSTALL_CLICK),
593 scopes::Variant(_("Go to Accounts")));
594 auto buttons = widgets.back();
595 widgets.pop_back();
596
597 scopes::VariantBuilder builder;
598 builder.add_tuple(
599 {
600 {"id", scopes::Variant(click::Preview::Actions::INSTALL_CLICK)},
601 {"label", scopes::Variant(_("Go to Accounts"))},
602 {"download_url", scopes::Variant(download_url)},
603 {"download_sha512", scopes::Variant(download_sha512)},
604 });
605 buttons.add_attribute_value("actions", builder.end());
606 oa_client.register_account_login_item(buttons,
607 scopes::OnlineAccountClient::PostLoginAction::ContinueActivation,
608 scopes::OnlineAccountClient::PostLoginAction::DoNothing);
609 widgets.push_back(buttons);
610 return widgets;
611}
612
613scopes::PreviewWidgetList PreviewStrategy::errorWidgets(const scopes::Variant& title,488scopes::PreviewWidgetList PreviewStrategy::errorWidgets(const scopes::Variant& title,
614 const scopes::Variant& summary,489 const scopes::Variant& summary,
615 const scopes::Variant& action_id,490 const scopes::Variant& action_id,
@@ -639,129 +514,6 @@
639 return widgets;514 return widgets;
640}515}
641516
642void PreviewStrategy::invalidateScope(const std::string& scope_id)
643{
644 run_under_qt([scope_id]() {
645 PackageManager::invalidate_results(scope_id);
646 });
647}
648
649// class DownloadErrorPreview
650
651DownloadErrorPreview::DownloadErrorPreview(const unity::scopes::Result &result)
652 : PreviewStrategy(result)
653{
654}
655
656DownloadErrorPreview::~DownloadErrorPreview()
657{
658
659}
660
661void DownloadErrorPreview::run(const unity::scopes::PreviewReplyProxy &reply)
662{
663 // NOTE: no details used by downloadErrorWidgets(), so no need to
664 // call populateDetails() here.
665 reply->push(downloadErrorWidgets());
666}
667
668// class InstallingPreview
669
670InstallingPreview::InstallingPreview(const std::string &download_url,
671 const std::string &download_sha512,
672 const unity::scopes::Result &result,
673 const QSharedPointer<click::web::Client>& client,
674 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager,
675 std::shared_ptr<click::DepartmentsDb> depts) :
676 PreviewStrategy(result, client),
677 DepartmentUpdater(depts),
678 download_url(download_url),
679 download_sha512(download_sha512),
680 dm(new DownloadManager(client, manager)),
681 depts_db(depts)
682{
683}
684
685InstallingPreview::~InstallingPreview()
686{
687}
688
689void InstallingPreview::startLauncherAnimation(const PackageDetails &details)
690{
691 Launcher l(LAUNCHER_BUSNAME, LAUNCHER_OBJECT_PATH, QDBusConnection::sessionBus());
692 l.startInstallation(QString::fromStdString(details.package.title),
693 QString::fromStdString(details.package.icon_url),
694 QString::fromStdString(details.package.name));
695
696}
697
698void InstallingPreview::run(const unity::scopes::PreviewReplyProxy &reply)
699{
700 qDebug() << "Starting installation" << QString(download_url.c_str()) << QString(download_sha512.c_str());
701 std::promise<bool> promise;
702 auto future = promise.get_future();
703 run_under_qt([this, reply, &promise]() {
704 dm->start(download_url, download_sha512, result["name"].get_string(),
705 [this, reply, &promise] (std::string msg, DownloadManager::Error dmerr){
706 switch (dmerr)
707 {
708 case DownloadManager::Error::DownloadInstallError:
709 qWarning() << "Error received from UDM during startDownload:" << msg.c_str();
710 reply->push(downloadErrorWidgets());
711 promise.set_value(false);
712 break;
713 case DownloadManager::Error::CredentialsError:
714 qWarning() << "InstallingPreview got error in getting credentials during startDownload";
715 reply->push(loginErrorWidgets(download_url, download_sha512));
716 promise.set_value(false);
717 break;
718 case DownloadManager::Error::NoError: {
719 std::string object_path = msg;
720 qDebug() << "Successfully created UDM Download.";
721 populateDetails([this, reply, object_path](const PackageDetails &details) {
722 store_department(details);
723 pushPackagePreviewWidgets(cachedWidgets, details, progressBarWidget(object_path));
724 startLauncherAnimation(details);
725 },
726 [this, reply, &promise](const ReviewList& reviewlist,
727 click::Reviews::Error error) {
728 if (error == click::Reviews::Error::NoError) {
729 auto const revs = reviewsWidgets(reviewlist);
730 cachedWidgets.push(revs);
731 cachedWidgets.layout.appendToColumn(cachedWidgets.layout.singleColumn.column1, revs);
732 cachedWidgets.layout.appendToColumn(cachedWidgets.layout.twoColumns.column1, revs);
733 } else {
734 qDebug() << "There was an error getting reviews for:" << result["name"].get_string().c_str();
735 }
736 cachedWidgets.flush(reply);
737 promise.set_value(true);
738 });
739 break;
740 }
741 default:
742 qCritical() << "Unknown error occurred downloading.";
743 promise.set_value(false);
744 break;
745 }
746 });
747 });
748 future.get();
749 reply->finished();
750}
751
752scopes::PreviewWidgetList PreviewStrategy::progressBarWidget(const std::string& object_path)
753{
754 scopes::PreviewWidgetList widgets;
755 scopes::PreviewWidget progress("download", "progress");
756 scopes::VariantMap tuple;
757 tuple["dbus-name"] = "com.canonical.applications.Downloader";
758 tuple["dbus-object"] = object_path;
759 progress.add_attribute_value("source", scopes::Variant(tuple));
760 widgets.push_back(progress);
761
762 return widgets;
763}
764
765// class InstalledPreview517// class InstalledPreview
766518
767InstalledPreview::InstalledPreview(const unity::scopes::Result& result,519InstalledPreview::InstalledPreview(const unity::scopes::Result& result,
@@ -778,163 +530,18 @@
778{530{
779}531}
780532
781std::string InstalledPreview::get_consumer_key()
782{
783 std::promise<std::string> promise;
784 auto future = promise.get_future();
785 QSharedPointer<click::CredentialsService> sso;
786
787 qt::core::world::enter_with_task([this, &sso, &promise]() {
788 sso.reset(new click::CredentialsService());
789
790 QObject::connect(sso.data(), &click::CredentialsService::credentialsFound,
791 [&promise, &sso](const UbuntuOne::Token& token) {
792 qDebug() << "Credentials found";
793 sso.clear();
794 try {
795 promise.set_value(token.consumerKey().toStdString());
796 } catch (const std::future_error&) {
797 // Ignore promise_already_satisfied
798 }
799 });
800 QObject::connect(sso.data(), &click::CredentialsService::credentialsNotFound,
801 [&promise, &sso]() {
802 qDebug() << "No credentials found";
803 sso.clear();
804 try {
805 promise.set_value("");
806 } catch (const std::future_error&) {
807 // Ignore promise_already_satisfied
808 }
809 });
810
811 sso->getCredentials();
812 qDebug() << "getCredentials finished";
813 });
814 return future.get();
815}
816
817scopes::PreviewWidget InstalledPreview::createRatingWidget(const click::Review& review) const
818{
819 scopes::PreviewWidget rating("rating", "rating-input");
820
821 if (review.id != 0) {
822 qDebug() << "Review for current user already exists, review id:" << review.id;
823 rating = scopes::PreviewWidget(std::to_string(review.id), "rating-edit"); // pass review id via widget id
824 rating.add_attribute_value("review", scopes::Variant(review.review_text));
825 rating.add_attribute_value("rating", scopes::Variant(review.rating));
826 rating.add_attribute_value("author", scopes::Variant(review.reviewer_name));
827 }
828
829 return rating;
830}
831
832void InstalledPreview::run(unity::scopes::PreviewReplyProxy const& reply)533void InstalledPreview::run(unity::scopes::PreviewReplyProxy const& reply)
833{534{
834 const bool force_cache = (metadata.internet_connectivity() == scopes::QueryMetadata::ConnectivityStatus::Disconnected);535 const bool force_cache = (metadata.internet_connectivity() == scopes::QueryMetadata::ConnectivityStatus::Disconnected);
835 qDebug() << "preview, force_cache=" << force_cache << ", conn status=" << (int)metadata.internet_connectivity();536 qDebug() << "preview, force_cache=" << force_cache << ", conn status=" << (int)metadata.internet_connectivity();
836537
837 // Check if the user is submitting a rating, so we can submit it.
838 Review review;
839 review.rating = 0;
840 std::string widget_id;
841 // We use a try/catch here, as scope_data() can be a dict, but not have
842 // the values we need, which will result in an exception thrown.
843 try {
844 auto metadict = metadata.scope_data().get_dict();
845 review.rating = metadict["rating"].get_int();
846 review.review_text = metadict["review"].get_string();
847 widget_id = metadict["widget_id"].get_string();
848 } catch(...) {
849 // Do nothing as we are not submitting a review.
850 }
851
852 auto userid = get_consumer_key();
853
854 //
855 // Get the click manifest.538 // Get the click manifest.
856 Manifest manifest;539 Manifest manifest;
857 std::promise<Manifest> manifest_promise;
858 std::future<Manifest> manifest_future = manifest_promise.get_future();
859 std::string app_name = result["name"].get_string();540 std::string app_name = result["name"].get_string();
860 if (!app_name.empty() && !std::regex_match(app_name, desktop_match)) {
861 qt::core::world::enter_with_task([&]() {
862 click::Interface().get_manifest_for_app(app_name,
863 [&](Manifest found_manifest, InterfaceError error) {
864 qDebug() << "Got manifest for:" << app_name.c_str();
865
866 // Fill in required data about the package being reviewed.
867 review.package_name = found_manifest.name;
868 review.package_version = found_manifest.version;
869
870 if (error != click::InterfaceError::NoError) {
871 qDebug() << "There was an error getting the manifest for:" << app_name.c_str();
872 }
873 manifest_promise.set_value(found_manifest);
874 });
875 });
876 manifest = manifest_future.get();
877 if (review.rating > 0) {
878 std::promise<bool> submit_promise;
879 std::future<bool> submit_future = submit_promise.get_future();
880 qt::core::world::enter_with_task([this, review, &submit_promise, widget_id]() mutable {
881 if (widget_id == "rating") {
882 submit_operation = reviews->submit_review(review,
883 [&submit_promise](click::Reviews::Error){
884 // TODO: Need to handle errors properly.
885 submit_promise.set_value(true);
886 });
887
888 } else {
889 try {
890 review.id = std::stoul(widget_id);
891 qDebug() << "Updating review" << review.id << "with '" << QString::fromStdString(review.review_text) << "'";
892 submit_operation = reviews->edit_review(review,
893 [&submit_promise](click::Reviews::Error){
894 // TODO: Need to handle errors properly.
895 submit_promise.set_value(true);
896 });
897 } catch (const std::exception &e) {
898 qWarning() << "Failed to update review:" << QString::fromStdString(e.what()) << " review widget:" << QString::fromStdString(widget_id);
899 submit_promise.set_value(false);
900 }
901 }
902 });
903 submit_future.get();
904 }
905 }
906 populateDetails([this, reply, manifest, app_name](const PackageDetails &details){541 populateDetails([this, reply, manifest, app_name](const PackageDetails &details){
907 cachedDetails = details;542 cachedDetails = details;
908 store_department(details);543 store_department(details);
909 pushPackagePreviewWidgets(cachedWidgets, details, createButtons(manifest));544 pushPackagePreviewWidgets(cachedWidgets, details, createButtons(manifest));
910 },
911 [this, reply, &review, manifest, userid](const ReviewList& reviewlist,
912 click::Reviews::Error error) {
913 auto reviews = bring_to_front(reviewlist, userid);
914 if (manifest.removable && !cachedDetails.download_url.empty()) {
915 scopes::PreviewWidgetList review_input;
916 bool has_reviewed = reviews.size() > 0 && reviews.front().reviewer_username == userid;
917
918 Review existing_review;
919 existing_review.id = 0;
920 if (has_reviewed) {
921 existing_review = reviews.front();
922 reviews.pop_front();
923 }
924 review_input.push_back(createRatingWidget(existing_review));
925 cachedWidgets.push(review_input);
926 cachedWidgets.layout.appendToColumn(cachedWidgets.layout.singleColumn.column1, review_input);
927 cachedWidgets.layout.appendToColumn(cachedWidgets.layout.twoColumns.column1, review_input);
928 }
929
930 if (error == click::Reviews::Error::NoError) {
931 auto const revs = reviewsWidgets(reviews);
932 cachedWidgets.push(revs);
933 cachedWidgets.layout.appendToColumn(cachedWidgets.layout.singleColumn.column1, revs);
934 cachedWidgets.layout.appendToColumn(cachedWidgets.layout.twoColumns.column1, revs);
935 } else {
936 qDebug() << "There was an error getting reviews for:" << result["name"].get_string().c_str();
937 }
938 cachedWidgets.flush(reply);545 cachedWidgets.flush(reply);
939 reply->finished();546 reply->finished();
940 }, force_cache);547 }, force_cache);
@@ -965,16 +572,6 @@
965 qDebug() << "Adding button" << QString::fromStdString(open_label) << "-"572 qDebug() << "Adding button" << QString::fromStdString(open_label) << "-"
966 << QString::fromStdString(uri);573 << QString::fromStdString(uri);
967 }574 }
968 if (manifest.removable)
969 {
970 auto price = result.contains("price") ? result["price"].get_double() : 0.00f;
971 if (price == 0.00f) {
972 builder.add_tuple({
973 {"id", scopes::Variant(click::Preview::Actions::UNINSTALL_CLICK)},
974 {"label", scopes::Variant(_("Uninstall"))}
975 });
976 }
977 }
978 if (!uri.empty() || manifest.removable) {575 if (!uri.empty() || manifest.removable) {
979 buttons.add_attribute_value("actions", builder.end());576 buttons.add_attribute_value("actions", builder.end());
980 widgets.push_back(buttons);577 widgets.push_back(buttons);
@@ -1032,203 +629,4 @@
1032 reply->push({actions});629 reply->push({actions});
1033}630}
1034631
1035// class PurchasingPreview
1036
1037PurchasingPreview::PurchasingPreview(const unity::scopes::Result& result,
1038 const QSharedPointer<click::web::Client>& client)
1039 : PreviewStrategy(result, client)
1040{
1041}
1042
1043PurchasingPreview::~PurchasingPreview()
1044{
1045}
1046
1047void PurchasingPreview::run(unity::scopes::PreviewReplyProxy const& reply)
1048{
1049 populateDetails([this, reply](const PackageDetails &details){
1050 reply->push(purchasingWidgets(details));
1051 },
1052 [this, reply](const click::ReviewList&, click::Reviews::Error) {
1053 reply->finished();
1054 });
1055}
1056
1057scopes::PreviewWidgetList PurchasingPreview::purchasingWidgets(const PackageDetails &/*details*/)
1058{
1059 scopes::PreviewWidgetList widgets;
1060 return widgets;
1061}
1062
1063// class UninstallConfirmationPreview
1064
1065UninstallConfirmationPreview::UninstallConfirmationPreview(const unity::scopes::Result& result)
1066 : PreviewStrategy(result)
1067{
1068}
1069
1070UninstallConfirmationPreview::~UninstallConfirmationPreview()
1071{
1072}
1073
1074void UninstallConfirmationPreview::run(unity::scopes::PreviewReplyProxy const& reply)
1075{
1076 // NOTE: no need to populateDetails() here.
1077 scopes::PreviewWidgetList widgets;
1078
1079 scopes::PreviewWidget header("hdr", "header");
1080 header.add_attribute_value("title", scopes::Variant(_("Confirmation")));
1081 std::string title = result["title"].get_string();
1082 // TRANSLATORS: Do NOT translate ${title} here.
1083 std::string message = _("Uninstall ${title}?");
1084 boost::replace_first(message, "${title}", title);
1085 header.add_attribute_value("subtitle", scopes::Variant(message));
1086 widgets.push_back(header);
1087
1088 scopes::PreviewWidget buttons("buttons", "actions");
1089 scopes::VariantBuilder builder;
1090 builder.add_tuple({
1091 {"id", scopes::Variant(click::Preview::Actions::SHOW_INSTALLED)},
1092 {"label", scopes::Variant(_("Cancel"))}
1093 });
1094 builder.add_tuple({
1095 {"id", scopes::Variant(click::Preview::Actions::CONFIRM_UNINSTALL)},
1096 {"label", scopes::Variant(_("Confirm"))}
1097 });
1098 buttons.add_attribute_value("actions", builder.end());
1099 widgets.push_back(buttons);
1100
1101 reply->push(widgets);
1102}
1103
1104// class UninstalledPreview
1105
1106UninstalledPreview::UninstalledPreview(const unity::scopes::Result& result,
1107 const unity::scopes::ActionMetadata& metadata,
1108 const QSharedPointer<click::web::Client>& client,
1109 const std::shared_ptr<click::DepartmentsDb>& depts,
1110 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager)
1111 : PreviewStrategy(result, client),
1112 DepartmentUpdater(depts),
1113 metadata(metadata),
1114 dm(new DownloadManager(client, manager))
1115{
1116 qDebug() << "Creating new UninstalledPreview for result" << QString::fromStdString(result["name"].get_string());
1117}
1118
1119UninstalledPreview::~UninstalledPreview()
1120{
1121}
1122
1123void UninstalledPreview::run(unity::scopes::PreviewReplyProxy const& reply)
1124{
1125 const bool force_cache = (metadata.internet_connectivity() == scopes::QueryMetadata::ConnectivityStatus::Disconnected);
1126 qDebug() << "preview, force_cache=" << force_cache << ", conn status=" << (int)metadata.internet_connectivity();
1127
1128 qDebug() << "in UninstalledPreview::run, about to populate details";
1129 populateDetails([this, reply](const PackageDetails &details){
1130 store_department(details);
1131 found_details = details;
1132 },
1133 [this, reply](const ReviewList& reviewlist,
1134 click::Reviews::Error reviewserror) {
1135 std::string app_name = result["name"].get_string();
1136 dm->get_progress(app_name,
1137 [this, reply, reviewlist, reviewserror](std::string object_path){
1138 found_object_path = object_path;
1139 scopes::PreviewWidgetList button_widgets;
1140 if(found_object_path.empty()) {
1141 button_widgets = uninstalledActionButtonWidgets(found_details);
1142 } else {
1143 button_widgets = progressBarWidget(found_object_path);
1144 }
1145 qDebug() << "Pushed button action widgets.";
1146 pushPackagePreviewWidgets(cachedWidgets, found_details, button_widgets);
1147 qDebug() << "Pushed package details widgets.";
1148 if (reviewserror == click::Reviews::Error::NoError) {
1149 qDebug() << "Pushing reviews widgets.";
1150 auto const revs = reviewsWidgets(reviewlist);
1151 cachedWidgets.push(revs);
1152 cachedWidgets.layout.appendToColumn(cachedWidgets.layout.singleColumn.column1, revs);
1153 cachedWidgets.layout.appendToColumn(cachedWidgets.layout.twoColumns.column1, revs);
1154 } else {
1155 qDebug() << "There was an error getting reviews for:" << result["name"].get_string().c_str();
1156 }
1157 cachedWidgets.flush(reply);
1158 reply->finished();
1159 qDebug() << "---------- Finished reply for:" << result["name"].get_string().c_str();
1160 });
1161 }, force_cache);
1162}
1163
1164scopes::PreviewWidgetList UninstalledPreview::uninstalledActionButtonWidgets(const PackageDetails &details)
1165{
1166 scopes::PreviewWidgetList widgets;
1167 auto price = result["price"].get_double();
1168
1169 if (price == double(0.00)
1170 || result["purchased"].get_bool() == false) {
1171 scopes::PreviewWidget buttons("buttons", "actions");
1172 scopes::VariantBuilder builder;
1173 builder.add_tuple(
1174 {
1175 {"id", scopes::Variant(click::Preview::Actions::INSTALL_CLICK)},
1176 {"label", scopes::Variant(_("Install"))},
1177 {"download_url", scopes::Variant(details.download_url)},
1178 {"download_sha512", scopes::Variant(details.download_sha512)},
1179 });
1180 buttons.add_attribute_value("actions", builder.end());
1181 oa_client.register_account_login_item(buttons,
1182 scopes::OnlineAccountClient::PostLoginAction::ContinueActivation,
1183 scopes::OnlineAccountClient::PostLoginAction::DoNothing);
1184 widgets.push_back(buttons);
1185 }
1186
1187 return widgets;
1188}
1189
1190// class UninstallingPreview : public UninstalledPreview
1191
1192// TODO: this class should be removed once uninstall() is handled elsewhere.
1193UninstallingPreview::UninstallingPreview(const unity::scopes::Result& result,
1194 const unity::scopes::ActionMetadata& metadata,
1195 const QSharedPointer<click::web::Client>& client,
1196 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager)
1197 : UninstalledPreview(result, metadata, client, nullptr, manager)
1198{
1199}
1200
1201UninstallingPreview::~UninstallingPreview()
1202{
1203}
1204
1205void UninstallingPreview::run(unity::scopes::PreviewReplyProxy const& reply)
1206{
1207 qDebug() << "in UninstallingPreview::run, calling uninstall";
1208 uninstall();
1209 qDebug() << "in UninstallingPreview::run, calling UninstalledPreview::run()";
1210 UninstalledPreview::run(reply);
1211}
1212
1213void UninstallingPreview::uninstall()
1214{
1215 click::Package package;
1216 package.title = result.title();
1217 package.name = result["name"].get_string();
1218 package.version = result["version"].get_string();
1219 qt::core::world::enter_with_task([this, package] ()
1220 {
1221 click::PackageManager manager;
1222 manager.uninstall(package, [&](int code, std::string stderr_content) {
1223 if (code != 0) {
1224 qDebug() << "Error removing package:" << stderr_content.c_str();
1225 } else {
1226 qDebug() << "successfully removed package";
1227
1228 }
1229 } );
1230 });
1231}
1232
1233
1234} // namespace click632} // namespace click
1235633
=== modified file 'libclickscope/click/preview.h'
--- libclickscope/click/preview.h 2016-10-24 21:26:23 +0000
+++ libclickscope/click/preview.h 2017-01-10 16:06:37 +0000
@@ -31,9 +31,7 @@
31#define CLICKPREVIEW_H31#define CLICKPREVIEW_H
3232
33#include <click/index.h>33#include <click/index.h>
34#include <click/download-manager.h>
35#include <click/qtbridge.h>34#include <click/qtbridge.h>
36#include "reviews.h"
3735
38#include <click/network_access_manager.h>36#include <click/network_access_manager.h>
3937
@@ -105,14 +103,7 @@
105 PreviewStrategy* build_strategy(const unity::scopes::Result& result,103 PreviewStrategy* build_strategy(const unity::scopes::Result& result,
106 const unity::scopes::ActionMetadata& metadata,104 const unity::scopes::ActionMetadata& metadata,
107 const QSharedPointer<web::Client> &client,105 const QSharedPointer<web::Client> &client,
108 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager,
109 std::shared_ptr<click::DepartmentsDb> depts);106 std::shared_ptr<click::DepartmentsDb> depts);
110 virtual PreviewStrategy* build_installing(const std::string& download_url,
111 const std::string& download_sha512,
112 const unity::scopes::Result& result,
113 const QSharedPointer<click::web::Client>& client,
114 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager,
115 std::shared_ptr<click::DepartmentsDb> depts);
116public:107public:
117 UNITY_DEFINES_PTRS(Preview);108 UNITY_DEFINES_PTRS(Preview);
118 struct Actions109 struct Actions
@@ -145,7 +136,6 @@
145 std::shared_future<void> const& qt_ready = std::future<void>());136 std::shared_future<void> const& qt_ready = std::future<void>());
146 virtual ~Preview();137 virtual ~Preview();
147 void choose_strategy(const QSharedPointer<web::Client> &client,138 void choose_strategy(const QSharedPointer<web::Client> &client,
148 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager,
149 std::shared_ptr<click::DepartmentsDb> depts);139 std::shared_ptr<click::DepartmentsDb> depts);
150 // From unity::scopes::PreviewQuery140 // From unity::scopes::PreviewQuery
151 void cancelled() override;141 void cancelled() override;
@@ -168,20 +158,13 @@
168 const scopes::PreviewWidgetList& button_area_widgets);158 const scopes::PreviewWidgetList& button_area_widgets);
169159
170 virtual void run_under_qt(const std::function<void ()> &task);160 virtual void run_under_qt(const std::function<void ()> &task);
171 virtual void invalidateScope(const std::string& scope_id);
172161
173protected:162protected:
174 virtual void populateDetails(std::function<void(const PackageDetails &)> details_callback,163 virtual void populateDetails(std::function<void(const PackageDetails &)> details_callback,
175 std::function<void(const click::ReviewList&,
176 click::Reviews::Error)> reviews_callback,
177 bool force_cache = false);164 bool force_cache = false);
178 virtual scopes::PreviewWidgetList headerWidgets(const PackageDetails &details);165 virtual scopes::PreviewWidgetList headerWidgets(const PackageDetails &details);
179 virtual scopes::PreviewWidgetList screenshotsWidgets(const PackageDetails &details);166 virtual scopes::PreviewWidgetList screenshotsWidgets(const PackageDetails &details);
180 virtual scopes::PreviewWidgetList descriptionWidgets(const PackageDetails &details);167 virtual scopes::PreviewWidgetList descriptionWidgets(const PackageDetails &details);
181 virtual scopes::PreviewWidgetList progressBarWidget(const std::string& object_path);
182 virtual scopes::PreviewWidgetList reviewsWidgets(const click::ReviewList &reviewlist);
183 virtual scopes::PreviewWidgetList downloadErrorWidgets();
184 virtual scopes::PreviewWidgetList loginErrorWidgets(const std::string& download_url, const std::string& download_sha512);
185 virtual scopes::PreviewWidgetList errorWidgets(const scopes::Variant& title,168 virtual scopes::PreviewWidgetList errorWidgets(const scopes::Variant& title,
186 const scopes::Variant& summary,169 const scopes::Variant& summary,
187 const scopes::Variant& action_id,170 const scopes::Variant& action_id,
@@ -199,45 +182,7 @@
199 QSharedPointer<click::web::Client> client;182 QSharedPointer<click::web::Client> client;
200 QSharedPointer<click::Index> index;183 QSharedPointer<click::Index> index;
201 click::web::Cancellable index_operation;184 click::web::Cancellable index_operation;
202 QSharedPointer<click::Reviews> reviews;
203 click::web::Cancellable reviews_operation;
204 click::web::Cancellable submit_operation;
205 scopes::OnlineAccountClient oa_client;185 scopes::OnlineAccountClient oa_client;
206 click::web::Cancellable purchase_operation;
207};
208
209class DownloadErrorPreview : public PreviewStrategy
210{
211public:
212 DownloadErrorPreview(const unity::scopes::Result& result);
213
214 virtual ~DownloadErrorPreview();
215
216 void run(unity::scopes::PreviewReplyProxy const& reply) override;
217};
218
219class InstallingPreview : public PreviewStrategy, public DepartmentUpdater
220{
221public:
222 InstallingPreview(const unity::scopes::Result& result) : PreviewStrategy(result) {}
223 InstallingPreview(const std::string& download_url,
224 const std::string& download_sha512,
225 const unity::scopes::Result& result,
226 const QSharedPointer<click::web::Client>& client,
227 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager,
228 std::shared_ptr<click::DepartmentsDb> depts);
229
230 virtual ~InstallingPreview();
231
232 void run(unity::scopes::PreviewReplyProxy const& reply) override;
233
234protected:
235 std::string download_url;
236 std::string download_sha512;
237 QSharedPointer<click::DownloadManager> dm;
238 std::shared_ptr<click::DepartmentsDb> depts_db;
239 CachedPreviewWidgets cachedWidgets;
240 void startLauncherAnimation(const PackageDetails& details);
241};186};
242187
243class InstalledPreview : public PreviewStrategy, public DepartmentUpdater188class InstalledPreview : public PreviewStrategy, public DepartmentUpdater
@@ -253,9 +198,7 @@
253 void run(unity::scopes::PreviewReplyProxy const& reply) override;198 void run(unity::scopes::PreviewReplyProxy const& reply) override;
254199
255 std::string getApplicationUri(const Manifest& manifest);200 std::string getApplicationUri(const Manifest& manifest);
256 std::string get_consumer_key();
257 scopes::PreviewWidgetList createButtons(const click::Manifest& manifest);201 scopes::PreviewWidgetList createButtons(const click::Manifest& manifest);
258 scopes::PreviewWidget createRatingWidget(const click::Review& review) const;
259202
260private:203private:
261 scopes::ActionMetadata metadata;204 scopes::ActionMetadata metadata;
@@ -270,71 +213,6 @@
270 void run(unity::scopes::PreviewReplyProxy const& reply) override;213 void run(unity::scopes::PreviewReplyProxy const& reply) override;
271};214};
272215
273class PurchasingPreview : public PreviewStrategy
274{
275public:
276 PurchasingPreview(const unity::scopes::Result& result,
277 const QSharedPointer<click::web::Client>& client);
278 virtual ~PurchasingPreview();
279
280 void run(unity::scopes::PreviewReplyProxy const& reply) override;
281
282protected:
283 virtual scopes::PreviewWidgetList purchasingWidgets(const PackageDetails &);
284};
285
286class UninstallConfirmationPreview : public PreviewStrategy
287{
288public:
289 UninstallConfirmationPreview(const unity::scopes::Result& result);
290
291 virtual ~UninstallConfirmationPreview();
292
293 void run(unity::scopes::PreviewReplyProxy const& reply) override;
294};
295
296class UninstalledPreview : public PreviewStrategy, public DepartmentUpdater
297{
298public:
299 UninstalledPreview(const unity::scopes::Result& result,
300 const unity::scopes::ActionMetadata& metadata,
301 const QSharedPointer<click::web::Client>& client,
302 const std::shared_ptr<click::DepartmentsDb>& depts,
303 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager);
304
305 virtual ~UninstalledPreview();
306
307 void run(unity::scopes::PreviewReplyProxy const& reply) override;
308 virtual scopes::PreviewWidgetList uninstalledActionButtonWidgets(const PackageDetails &details);
309
310protected:
311 scopes::ActionMetadata metadata;
312 PackageDetails found_details;
313 CachedPreviewWidgets cachedWidgets;
314 std::string found_object_path;
315
316 QSharedPointer<click::DownloadManager> dm;
317};
318
319// TODO: this is only necessary to perform uninstall.
320// That should be moved to a separate action, and this class removed.
321class UninstallingPreview : public UninstalledPreview
322{
323public:
324 UninstallingPreview(const unity::scopes::Result& result,
325 const unity::scopes::ActionMetadata& metadata,
326 const QSharedPointer<click::web::Client>& client,
327 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager);
328
329 virtual ~UninstallingPreview();
330
331 void run(unity::scopes::PreviewReplyProxy const& reply) override;
332
333protected:
334 void uninstall();
335
336};
337
338} // namespace click216} // namespace click
339217
340#endif218#endif
341219
=== removed file 'libclickscope/click/reviews.cpp'
--- libclickscope/click/reviews.cpp 2016-05-25 16:19:51 +0000
+++ libclickscope/click/reviews.cpp 1970-01-01 00:00:00 +0000
@@ -1,245 +0,0 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include <cstdlib>
31#include <algorithm>
32
33#include <boost/property_tree/ptree.hpp>
34#include <boost/property_tree/json_parser.hpp>
35#include <boost/foreach.hpp>
36
37#include <click/configuration.h>
38
39#include <json/value.h>
40#include <json/writer.h>
41
42#include "reviews.h"
43
44namespace click
45{
46
47bool operator== (const Review& lhs, const Review &rhs)
48{
49 return lhs.id == rhs.id &&
50 lhs.rating == rhs.rating &&
51 lhs.usefulness_favorable == rhs.usefulness_favorable &&
52 lhs.usefulness_total == rhs.usefulness_total &&
53 lhs.hide == rhs.hide &&
54 lhs.date_created == rhs.date_created &&
55 lhs.date_deleted == rhs.date_deleted &&
56 lhs.package_name == rhs.package_name &&
57 lhs.package_version == rhs.package_version &&
58 lhs.language == rhs.language &&
59 lhs.summary == rhs.summary &&
60 lhs.review_text == rhs.review_text &&
61 lhs.reviewer_name == rhs.reviewer_name &&
62 lhs.reviewer_username == rhs.reviewer_username;
63}
64
65ReviewList review_list_from_json (const std::string& json)
66{
67 std::istringstream stream(json);
68
69 boost::property_tree::ptree tree;
70 boost::property_tree::read_json(stream, tree);
71
72 ReviewList reviews;
73
74 BOOST_FOREACH(boost::property_tree::ptree::value_type &value, tree)
75 {
76 assert(value.first.empty()); // array elements have no names
77 auto node = value.second;
78 Review review;
79
80 review.id = node.get<uint32_t>("id");
81 review.rating = node.get<int>("rating");
82 review.usefulness_favorable = node.get<uint32_t>("usefulness_favorable");
83 review.usefulness_total = node.get<uint32_t>("usefulness_total");
84 review.hide = node.get<bool>("hide");
85 review.date_created = node.get<std::string>("date_created");
86 review.date_deleted = node.get<std::string>("date_deleted");
87 review.package_name = node.get<std::string>("package_name");
88 review.package_version = node.get<std::string>("version");
89 review.language = node.get<std::string>("language");
90 review.summary = node.get<std::string>("summary");
91 review.review_text = node.get<std::string>("review_text");
92 review.reviewer_username = node.get<std::string>("reviewer_username");
93 review.reviewer_name = node.get<std::string>("reviewer_displayname", review.reviewer_username);
94
95 reviews.push_back(review);
96 }
97 return reviews;
98}
99
100ReviewList bring_to_front (const ReviewList& reviews, const std::string& userid)
101{
102 if (userid.size() == 0)
103 {
104 return reviews;
105 }
106 auto new_reviews = reviews;
107 auto it = std::find_if(new_reviews.begin(), new_reviews.end(), [userid](const Review& review) {
108 return review.reviewer_username == userid;
109 });
110 if (it != new_reviews.end() && it != new_reviews.begin()) {
111 // move own review to the front
112 auto const review = *it;
113 new_reviews.erase(it);
114 new_reviews.push_front(review);
115 }
116 return new_reviews;
117}
118
119Reviews::Reviews (const QSharedPointer<click::web::Client>& client)
120 : client(client)
121{
122}
123
124Reviews::~Reviews ()
125{
126}
127
128click::web::Cancellable Reviews::fetch_reviews (const std::string& package_name,
129 std::function<void(ReviewList, Error)> callback,
130 bool force_cache)
131{
132 click::web::CallParams params;
133 params.add(click::REVIEWS_QUERY_ARGNAME, package_name.c_str());
134 QSharedPointer<click::web::Response> response = client->call
135 (get_base_url() + click::REVIEWS_API_PATH, "GET", false,
136 std::map<std::string, std::string>{}, "", params, force_cache);
137
138 QObject::connect(response.data(), &click::web::Response::finished,
139 [=](QString reply) {
140 auto status = response->get_status_code();
141 click::ReviewList reviews;
142 if (status == 200) {
143 reviews = review_list_from_json(reply.toUtf8().constData());
144 callback(reviews, click::Reviews::Error::NoError);
145 } else {
146 callback(reviews, click::Reviews::Error::NetworkError);
147 }
148 });
149 QObject::connect(response.data(), &click::web::Response::error,
150 [=](QString) {
151 qDebug() << "Network error attempting to fetch reviews for:" << package_name.c_str();
152 callback(ReviewList(), click::Reviews::Error::NetworkError);
153 });
154
155 return click::web::Cancellable(response);
156}
157
158click::web::Cancellable Reviews::submit_review (const Review& review,
159 std::function<void(Error)> callback)
160{
161 std::map<std::string, std::string> headers({
162 {click::web::CONTENT_TYPE_HEADER, click::web::CONTENT_TYPE_JSON},
163 });
164 Json::Value root(Json::ValueType::objectValue);
165 root["package_name"] = review.package_name;
166 root["version"] = review.package_version;
167 root["rating"] = review.rating;
168 root["review_text"] = review.review_text;
169
170 root["arch_tag"] = click::Configuration().get_architecture();
171 /* NOTE: We only use the base language code for reviews, except for
172 * codes in the click::Configuration::FULL_LANG_CODES vector.
173 */
174 auto language = click::Configuration().get_language();
175 if (click::Configuration::is_full_lang_code(language)) {
176 root["language"] = language;
177 } else {
178 root["language"] = click::Configuration().get_language_base();
179 }
180
181 // NOTE: "summary" is a required field, but we don't have one. Use "".
182 root["summary"] = "Review";
183
184 qDebug() << "Rating" << review.package_name.c_str() << review.rating;
185
186 QSharedPointer<click::web::Response> response = client->call
187 (get_base_url() + click::REVIEWS_API_PATH, "POST", true,
188 headers, Json::FastWriter().write(root), click::web::CallParams());
189
190 QObject::connect(response.data(), &click::web::Response::finished,
191 [=](QString) {
192 qDebug() << "Review submitted for:" << review.package_name.c_str();
193 callback(Error::NoError);
194 });
195 QObject::connect(response.data(), &click::web::Response::error,
196 [=](QString) {
197 qCritical() << "Network error submitting a reviews for:" << review.package_name.c_str();
198 callback(Error::NetworkError);
199 });
200
201 return click::web::Cancellable(response);
202}
203
204click::web::Cancellable Reviews::edit_review (const Review& review,
205 std::function<void(Error)> callback)
206{
207 std::map<std::string, std::string> headers({
208 {click::web::CONTENT_TYPE_HEADER, click::web::CONTENT_TYPE_JSON},
209 });
210 Json::Value root(Json::ValueType::objectValue);
211 root["rating"] = review.rating;
212 root["review_text"] = review.review_text;
213 // NOTE: "summary" is a required field, but we don't have one. Use "".
214 root["summary"] = "Review";
215
216 qDebug() << "Rating" << review.package_name.c_str() << review.rating;
217
218 QSharedPointer<click::web::Response> response = client->call
219 (get_base_url() + click::REVIEWS_API_PATH + std::to_string(review.id) + "/", "PUT", true,
220 headers, Json::FastWriter().write(root), click::web::CallParams());
221
222 QObject::connect(response.data(), &click::web::Response::finished,
223 [=](QString) {
224 qDebug() << "Review updated for:" << review.package_name.c_str();
225 callback(Error::NoError);
226 });
227 QObject::connect(response.data(), &click::web::Response::error,
228 [=](QString) {
229 qCritical() << "Network error updating a review for:" << review.package_name.c_str();
230 callback(Error::NetworkError);
231 });
232
233 return click::web::Cancellable(response);
234}
235
236std::string Reviews::get_base_url ()
237{
238 const char *env_url = getenv(REVIEWS_BASE_URL_ENVVAR.c_str());
239 if (env_url != NULL) {
240 return env_url;
241 }
242 return click::REVIEWS_BASE_URL;
243}
244
245} //namespace click
2460
=== removed file 'libclickscope/click/reviews.h'
--- libclickscope/click/reviews.h 2016-04-27 14:06:29 +0000
+++ libclickscope/click/reviews.h 1970-01-01 00:00:00 +0000
@@ -1,95 +0,0 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#ifndef CLICK_REVIEWS_H
31#define CLICK_REVIEWS_H
32
33#include <functional>
34#include <string>
35#include <list>
36
37#include <click/webclient.h>
38
39namespace click
40{
41
42const std::string REVIEWS_BASE_URL_ENVVAR = "U1_REVIEWS_BASE_URL";
43const std::string REVIEWS_BASE_URL = "https://reviews.ubuntu.com";
44const std::string REVIEWS_API_PATH = "/click/api/1.0/reviews/";
45const std::string REVIEWS_QUERY_ARGNAME = "package_name";
46
47struct Review
48{
49 uint32_t id;
50 int rating;
51 uint32_t usefulness_favorable;
52 uint32_t usefulness_total;
53 bool hide;
54 std::string date_created;
55 std::string date_deleted;
56 std::string package_name;
57 std::string package_version;
58 std::string language;
59 std::string summary;
60 std::string review_text;
61 std::string reviewer_name;
62 std::string reviewer_username;
63};
64
65typedef std::list<Review> ReviewList;
66
67ReviewList review_list_from_json (const std::string& json);
68ReviewList bring_to_front (const ReviewList& reviews, const std::string& userid);
69
70class Reviews
71{
72protected:
73 QSharedPointer<web::Client> client;
74public:
75 enum class Error {NoError, CredentialsError, NetworkError};
76 Reviews() {}
77 Reviews(const QSharedPointer<click::web::Client>& client);
78 virtual ~Reviews();
79
80 virtual click::web::Cancellable fetch_reviews (const std::string& package_name,
81 std::function<void(ReviewList, Error)> callback,
82 bool force_cache = false);
83 click::web::Cancellable submit_review (const Review& review,
84 std::function<void(Error)> callback);
85 click::web::Cancellable edit_review (const Review& review,
86 std::function<void(Error)> callback);
87
88 static std::string get_base_url ();
89};
90
91bool operator==(const Review& lhs, const Review& rhs);
92
93} // namespace click
94
95#endif // CLICK_REVIEWS_H
960
=== modified file 'libclickscope/click/scope_activation.cpp'
--- libclickscope/click/scope_activation.cpp 2016-05-19 18:05:56 +0000
+++ libclickscope/click/scope_activation.cpp 2017-01-10 16:06:37 +0000
@@ -28,7 +28,6 @@
28 */28 */
2929
30#include "scope_activation.h"30#include "scope_activation.h"
31#include <click/download-manager.h>
32#include <click/package.h>31#include <click/package.h>
33#include <click/interface.h>32#include <click/interface.h>
34#include <click/qtbridge.h>33#include <click/qtbridge.h>
@@ -55,42 +54,3 @@
55{54{
56 hints_[key] = value;55 hints_[key] = value;
57}56}
58
59click::PerformUninstallAction::PerformUninstallAction(const unity::scopes::Result& result, const unity::scopes::ActionMetadata& metadata)
60 : unity::scopes::ActivationQueryBase(result, metadata)
61{
62}
63
64unity::scopes::ActivationResponse click::PerformUninstallAction::activate()
65{
66 std::promise<bool> uninstall_success_p;
67 std::future<bool> uninstall_success_f = uninstall_success_p.get_future();
68
69 auto const res = result();
70 click::Package package;
71 package.title = res.title();
72 package.name = res["name"].get_string();
73 package.version = res["version"].get_string();
74 qt::core::world::enter_with_task([this, package, &uninstall_success_p] ()
75 {
76 click::PackageManager manager;
77 manager.uninstall(package, [&](int code, std::string stderr_content) {
78 if (code != 0) {
79 qDebug() << "Error removing package:" << stderr_content.c_str();
80 uninstall_success_p.set_value(false);
81 } else {
82 qDebug() << "successfully removed package";
83 uninstall_success_p.set_value(true);
84 }
85 } );
86 });
87
88 if (uninstall_success_f.get())
89 {
90 if (res.contains("lonely_result") && res.value("lonely_result").get_bool())
91 {
92 return unity::scopes::ActivationResponse(unity::scopes::CannedQuery(APPS_SCOPE_ID.toUtf8().data()));
93 }
94 }
95 return unity::scopes::ActivationResponse(unity::scopes::ActivationResponse::ShowDash);
96}
9757
=== modified file 'libclickscope/click/scope_activation.h'
--- libclickscope/click/scope_activation.h 2016-05-18 12:38:46 +0000
+++ libclickscope/click/scope_activation.h 2017-01-10 16:06:37 +0000
@@ -37,13 +37,6 @@
37namespace click37namespace click
38{38{
3939
40class PerformUninstallAction: public unity::scopes::ActivationQueryBase
41{
42public:
43 PerformUninstallAction(const unity::scopes::Result& result, const unity::scopes::ActionMetadata& metadata);
44 unity::scopes::ActivationResponse activate() override;
45};
46
47class ScopeActivation : public unity::scopes::ActivationQueryBase40class ScopeActivation : public unity::scopes::ActivationQueryBase
48{41{
49 unity::scopes::ActivationResponse activate() override;42 unity::scopes::ActivationResponse activate() override;
5043
=== modified file 'libclickscope/tests/CMakeLists.txt'
--- libclickscope/tests/CMakeLists.txt 2016-10-24 21:26:23 +0000
+++ libclickscope/tests/CMakeLists.txt 2017-01-10 16:06:37 +0000
@@ -20,7 +20,6 @@
20add_executable (${LIBCLICKSCOPE_TESTS_TARGET}20add_executable (${LIBCLICKSCOPE_TESTS_TARGET}
21 mock_network_access_manager.h21 mock_network_access_manager.h
22 mock_ual.h22 mock_ual.h
23 mock_ubuntu_download_manager.h
24 mock_ubuntuone_credentials.h23 mock_ubuntuone_credentials.h
25 mock_webclient.h24 mock_webclient.h
26 fake_json.cpp25 fake_json.cpp
@@ -28,12 +27,10 @@
28 test_configuration.cpp27 test_configuration.cpp
29 test_departments.cpp28 test_departments.cpp
30 test_departments-db.cpp29 test_departments-db.cpp
31 test_download_manager.cpp
32 test_index.cpp30 test_index.cpp
33 test_interface.cpp31 test_interface.cpp
34 test_package.cpp32 test_package.cpp
35 test_preview.cpp33 test_preview.cpp
36 test_reviews.cpp
37 test_smartconnect.cpp34 test_smartconnect.cpp
38 test_utils.cpp35 test_utils.cpp
39 test_webclient.cpp36 test_webclient.cpp
@@ -46,8 +43,6 @@
4643
47 ${UNITY_SCOPES_LDFLAGS}44 ${UNITY_SCOPES_LDFLAGS}
48 ${UBUNTUONE_LDFLAGS}45 ${UBUNTUONE_LDFLAGS}
49 ${UBUNTU_DOWNLOAD_MANAGER_CLIENT_LDFLAGS}
50 ${UBUNTU_DOWNLOAD_MANAGER_COMMON_LDFLAGS}
51 ${JSON_CPP_LDFLAGS}46 ${JSON_CPP_LDFLAGS}
5247
53 gmock48 gmock
5449
=== removed file 'libclickscope/tests/mock_ubuntu_download_manager.h'
--- libclickscope/tests/mock_ubuntu_download_manager.h 2016-02-24 17:48:56 +0000
+++ libclickscope/tests/mock_ubuntu_download_manager.h 1970-01-01 00:00:00 +0000
@@ -1,140 +0,0 @@
1/*
2 * Copyright (C) 2014-2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#ifndef _MOCK_UBUNTU_DOWNLOAD_MANAGER_H_
31#define _MOCK_UBUNTU_DOWNLOAD_MANAGER_H_
32
33#include <QDBusConnection>
34#include <QDBusObjectPath>
35
36#include <ubuntu/download_manager/download.h>
37#include <ubuntu/download_manager/downloads_list.h>
38#include <ubuntu/download_manager/error.h>
39#include <ubuntu/download_manager/manager.h>
40
41#include <gmock/gmock.h>
42
43class MockDownload : public Ubuntu::DownloadManager::Download
44{
45public:
46 MockDownload() : Ubuntu::DownloadManager::Download(){};
47 MockDownload(Ubuntu::DownloadManager::Error *err) : Ubuntu::DownloadManager::Download(err) {};
48 // mock ALL methods so that we do not have an abstract class
49
50 MOCK_METHOD0(start, void());
51 MOCK_METHOD0(pause, void());
52 MOCK_METHOD0(resume, void());
53 MOCK_METHOD0(cancel, void());
54
55 MOCK_METHOD1(allowMobileDownload, void(bool));
56 MOCK_METHOD0(isMobileDownloadAllowed, bool());
57
58 MOCK_METHOD1(setThrottle, void(qulonglong));
59 MOCK_METHOD0(throttle, qulonglong());
60
61 MOCK_CONST_METHOD0(id, QString());
62
63 MOCK_METHOD1(setDestinationDir, void(const QString& path));
64 MOCK_METHOD0(metadata, QVariantMap());
65 MOCK_METHOD1(setMetadata, void(QVariantMap));
66 MOCK_METHOD0(progress, qulonglong());
67 MOCK_METHOD0(totalSize, qulonglong());
68
69 MOCK_CONST_METHOD0(clickPackage, QString());
70 MOCK_CONST_METHOD0(title, QString());
71 MOCK_CONST_METHOD0(showInIndicator, bool());
72
73 MOCK_CONST_METHOD0(isError, bool());
74 MOCK_CONST_METHOD0(error, Error*());
75 MOCK_METHOD0(headers, QMap<QString, QString>());
76 MOCK_METHOD1(setHeaders, void(QMap<QString, QString>));
77 MOCK_CONST_METHOD0(destinationApp, QString());
78
79 MOCK_METHOD0(collected, void());
80 MOCK_METHOD0(filePath, QString());
81 MOCK_METHOD0(state, Download::State());
82};
83
84class MockError : public Ubuntu::DownloadManager::Error
85{
86public:
87
88 MockError() : Ubuntu::DownloadManager::Error(Ubuntu::DownloadManager::Error::Type::Process, 0) {};
89 MOCK_METHOD0(errorString, QString());
90};
91
92class MockDownloadsList : public Ubuntu::DownloadManager::DownloadsList
93{
94public:
95
96 MockDownloadsList() : Ubuntu::DownloadManager::DownloadsList() {};
97
98 MOCK_CONST_METHOD0(downloads, QList<QSharedPointer<Ubuntu::DownloadManager::Download>>());
99 MOCK_CONST_METHOD0(isError, bool());
100 MOCK_CONST_METHOD0(error, Ubuntu::DownloadManager::Error*());
101};
102
103class MockSystemDownloadManager : public Ubuntu::DownloadManager::Manager
104{
105public:
106
107 MockSystemDownloadManager() : Ubuntu::DownloadManager::Manager() {};
108
109 MOCK_METHOD1(getDownloadForId, Download*(const QString&));
110 MOCK_METHOD1(createDownload,
111 void(DownloadStruct downStruct));
112 MOCK_METHOD3(createDownload,
113 void(DownloadStruct downStruct, DownloadCb cb, DownloadCb errCb));
114 MOCK_METHOD5(createDownload,
115 void(StructList downs, const QString &algorithm, bool allowed3G, const QVariantMap &metadata, StringMap headers));
116 MOCK_METHOD7(createDownload,
117 void(StructList downs, const QString &algorithm, bool allowed3G, const QVariantMap &metadata, StringMap headers, GroupCb cb, GroupCb errCb));
118
119 MOCK_METHOD2(getAllDownloads, void(const QString &appId, bool uncompleted));
120 MOCK_METHOD4(getAllDownloads, void(const QString &appId,
121 bool uncompleted,
122 DownloadsListCb cb,
123 DownloadsListCb errCb));
124 MOCK_METHOD2(getAllDownloadsWithMetadata, void(const QString &name,
125 const QString &value));
126
127 MOCK_METHOD4(getAllDownloadsWithMetadata, void(const QString &name,
128 const QString &value, MetadataDownloadsListCb cb,
129 MetadataDownloadsListCb errCb));
130
131 MOCK_CONST_METHOD0(isError, bool());
132 MOCK_CONST_METHOD0(lastError, Error*());
133 MOCK_METHOD1(allowMobileDataDownload, void(bool));
134 MOCK_METHOD0(isMobileDataDownload, bool());
135 MOCK_METHOD0(defaultThrottle, qulonglong());
136 MOCK_METHOD1(setDefaultThrottle, void(qulonglong));
137 MOCK_METHOD0(exit, void());
138};
139
140#endif /* _MOCK_UBUNTU_DOWNLOAD_MANAGER_H_ */
1410
=== modified file 'libclickscope/tests/test_bootstrap.cpp'
--- libclickscope/tests/test_bootstrap.cpp 2016-06-30 20:42:56 +0000
+++ libclickscope/tests/test_bootstrap.cpp 2017-01-10 16:06:37 +0000
@@ -27,7 +27,6 @@
27 * files in the program, then also delete it here.27 * files in the program, then also delete it here.
28 */28 */
29#include <click/configuration.h>29#include <click/configuration.h>
30#include <click/reviews.h>
31#include <click/webclient.h>30#include <click/webclient.h>
32#include <click/index.h>31#include <click/index.h>
3332
3433
=== removed file 'libclickscope/tests/test_download_manager.cpp'
--- libclickscope/tests/test_download_manager.cpp 2016-05-10 13:42:12 +0000
+++ libclickscope/tests/test_download_manager.cpp 1970-01-01 00:00:00 +0000
@@ -1,220 +0,0 @@
1/*
2 * Copyright (C) 2014-2016 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include <click/download-manager.h>
31#include <tests/mock_network_access_manager.h>
32#include <tests/mock_webclient.h>
33#include <tests/mock_ubuntu_download_manager.h>
34#include <tests/mock_ubuntuone_credentials.h>
35
36#include <gtest/gtest.h>
37#include <memory>
38
39using namespace ::testing;
40
41namespace udm = Ubuntu::DownloadManager;
42#include <ubuntu/download_manager/download_struct.h>
43
44namespace
45{
46const QString TEST_URL("http://test.local/");
47const QString TEST_SHA512("fake_hash");
48const QString TEST_HEADER_VALUE("test header value");
49const QString TEST_APP_ID("test_app_id");
50const QString TEST_CLICK_TOKEN_VALUE("test token value");
51const QString TEST_DOWNLOAD_ID("/com/ubuntu/download_manager/test");
52const QString TEST_DOWNLOADERROR_STRING("test downloadError string");
53
54
55class DownloadManagerTest : public ::testing::Test
56{
57protected:
58 QSharedPointer<MockClient> clientPtr;
59 QSharedPointer<MockNetworkAccessManager> namPtr;
60 QSharedPointer<MockSystemDownloadManager> sdmPtr;
61 QSharedPointer<MockCredentialsService> ssoPtr;
62 std::shared_ptr<click::DownloadManager> dmPtr;
63
64 virtual void SetUp()
65 {
66 ssoPtr.reset(new MockCredentialsService());
67 namPtr.reset(new MockNetworkAccessManager());
68 clientPtr.reset(new NiceMock<MockClient>(namPtr));
69 clientPtr->setCredentialsService(ssoPtr);
70 dmPtr.reset(new click::DownloadManager(clientPtr, sdmPtr));
71 }
72
73 MOCK_METHOD2(start_callback, void(std::string, click::DownloadManager::Error));
74 MOCK_METHOD1(progress_callback, void(std::string));
75};
76
77}
78
79TEST_F(DownloadManagerTest, testStartCallsWebservice)
80{
81 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
82 auto response = responseForReply(reply.asSharedPtr());
83
84 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
85 .Times(1)
86 .WillOnce(Return(response));
87
88 dmPtr->start("", "", "",
89 [](std::string, click::DownloadManager::Error) {});
90}
91
92TEST_F(DownloadManagerTest, testStartCallbackCalled)
93{
94 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
95 auto response = responseForReply(reply.asSharedPtr());
96
97 EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(0)));
98 EXPECT_CALL(reply.instance, readAll())
99 .Times(1)
100 .WillOnce(Return(""));
101 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
102 .Times(1)
103 .WillOnce(Return(response));
104 EXPECT_CALL(*this, start_callback(_, _)).Times(1);
105
106 dmPtr->start("", "", "",
107 [this](std::string msg, click::DownloadManager::Error err) {
108 start_callback(msg, err);
109 });
110 response->replyFinished();
111}
112
113TEST_F(DownloadManagerTest, testStartHTTPForbidden)
114{
115 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
116 auto response = responseForReply(reply.asSharedPtr());
117
118 EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(403)));
119 EXPECT_CALL(reply.instance, readAll())
120 .Times(1)
121 .WillOnce(Return(""));
122 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
123 .Times(1)
124 .WillOnce(Return(response));
125 EXPECT_CALL(*this, start_callback(StartsWith("Unhandled HTTP response code:"),
126 click::DownloadManager::Error::DownloadInstallError)).Times(1);
127
128 dmPtr->start("", "", "",
129 [this](std::string msg, click::DownloadManager::Error err) {
130 start_callback(msg, err);
131 });
132 response->replyFinished();
133}
134
135TEST_F(DownloadManagerTest, testStartHTTPError)
136{
137 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
138 auto response = responseForReply(reply.asSharedPtr());
139
140 EXPECT_CALL(reply.instance, errorString())
141 .WillOnce(Return(QString("ERROR")));
142 EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(404)));
143 EXPECT_CALL(reply.instance, readAll())
144 .Times(1)
145 .WillOnce(Return(""));
146 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
147 .Times(1)
148 .WillOnce(Return(response));
149 EXPECT_CALL(*this, start_callback("ERROR (203)",
150 click::DownloadManager::Error::DownloadInstallError)).Times(1);
151
152 dmPtr->start("", "", "",
153 [this](std::string msg, click::DownloadManager::Error err) {
154 start_callback(msg, err);
155 });
156 response->errorHandler(QNetworkReply::ContentNotFoundError);
157}
158
159TEST_F(DownloadManagerTest, testStartCredentialsError)
160{
161 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
162 auto response = responseForReply(reply.asSharedPtr());
163
164 EXPECT_CALL(reply.instance, errorString())
165 .WillOnce(Return(QString("ERROR")));
166 EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(401)));
167 EXPECT_CALL(reply.instance, readAll())
168 .Times(1)
169 .WillOnce(Return(""));
170 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
171 .Times(1)
172 .WillOnce(Return(response));
173 EXPECT_CALL(*ssoPtr, invalidateCredentials());
174 EXPECT_CALL(*this, start_callback("ERROR (201)",
175 click::DownloadManager::Error::CredentialsError)).Times(1);
176
177 dmPtr->start("", "", "test.package",
178 [this](std::string msg, click::DownloadManager::Error err) {
179 start_callback(msg, err);
180 });
181 response->errorHandler(QNetworkReply::ContentAccessDenied);
182}
183
184// FIXME: createDownload() SEGV under tests
185TEST_F(DownloadManagerTest, DISABLED_testStartDownloadCreated)
186{
187 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
188 auto response = responseForReply(reply.asSharedPtr());
189
190 EXPECT_CALL(reply.instance, rawHeader(QByteArray("X-Click-Token")))
191 .Times(1)
192 .WillOnce(Return(QString("clicktoken")));
193 EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(200)));
194 EXPECT_CALL(reply.instance, readAll())
195 .Times(1)
196 .WillOnce(Return(""));
197 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
198 .Times(1)
199 .WillOnce(Return(response));
200
201 EXPECT_CALL(*sdmPtr, createDownload(_, _, _));
202 dmPtr->start("", "", "test.package",
203 [this](std::string msg, click::DownloadManager::Error err) {
204 start_callback(msg, err);
205 });
206 response->replyFinished();
207}
208
209// FIXME: getAllDownloadsWithMetadata() SEGV under tests
210TEST_F(DownloadManagerTest, DISABLED_testGetProgressNoDownloads)
211{
212 EXPECT_CALL(*sdmPtr, getAllDownloadsWithMetadata(_, _, _, _))
213 .Times(1)
214 .WillOnce(InvokeArgument<3>(QStringLiteral(""), QStringLiteral(""),
215 nullptr));
216 dmPtr->get_progress("com.example.test",
217 [this](std::string object_path) {
218 progress_callback(object_path);
219 });
220}
2210
=== modified file 'libclickscope/tests/test_index.cpp'
--- libclickscope/tests/test_index.cpp 2016-12-02 18:37:59 +0000
+++ libclickscope/tests/test_index.cpp 2017-01-10 16:06:37 +0000
@@ -613,18 +613,6 @@
613 EXPECT_EQ(1u, lists.second.size());613 EXPECT_EQ(1u, lists.second.size());
614}614}
615615
616TEST_F(MockPackageManager, testUninstallCommandCorrect)
617{
618 click::Package package = {
619 "org.example.testapp", "Test App", 0.00,
620 "/tmp/foo.png",
621 "uri", "0.1.5", "app"
622 };
623 std::string expected = "pkcon -p remove org.example.testapp;0.1.5;all;local:click";
624 EXPECT_CALL(*this, execute_uninstall_command(expected, _)).Times(1);
625 uninstall(package, [](int, std::string) {});
626}
627
628class ExhibitionistIndex : public click::Index {616class ExhibitionistIndex : public click::Index {
629public:617public:
630 using click::Index::build_index_query;618 using click::Index::build_index_query;
631619
=== modified file 'libclickscope/tests/test_interface.cpp'
--- libclickscope/tests/test_interface.cpp 2016-12-02 18:37:59 +0000
+++ libclickscope/tests/test_interface.cpp 2017-01-10 16:06:37 +0000
@@ -114,7 +114,6 @@
114public:114public:
115 FakeClickInterface() {}115 FakeClickInterface() {}
116116
117 MOCK_CONST_METHOD1(get_manifest_json, std::string(const std::string&));
118 MOCK_CONST_METHOD0(installed_apps, std::list<std::shared_ptr<ual::Application>>());117 MOCK_CONST_METHOD0(installed_apps, std::list<std::shared_ptr<ual::Application>>());
119};118};
120119
@@ -485,79 +484,6 @@
485 Interface::add_theme_scheme("/usr/share/unity8/graphics/applicationIcons/contacts-app@18.png"));484 Interface::add_theme_scheme("/usr/share/unity8/graphics/applicationIcons/contacts-app@18.png"));
486}485}
487486
488TEST(ClickInterface, testManifestFromJsonOneApp)
489{
490 Manifest m = manifest_from_json(FAKE_JSON_MANIFEST_ONE_APP);
491 ASSERT_EQ(m.first_app_name, "fake-app");
492 ASSERT_TRUE(m.has_any_apps());
493 ASSERT_FALSE(m.has_any_scopes());
494}
495
496TEST(ClickInterface, testManifestFromJsonOneScope)
497{
498 Manifest m = manifest_from_json(FAKE_JSON_MANIFEST_ONE_SCOPE);
499 ASSERT_EQ(m.first_scope_id, "com.example.fake-scope_fake-scope-hook");
500 ASSERT_FALSE(m.has_any_apps());
501 ASSERT_TRUE(m.has_any_scopes());
502}
503
504TEST(ClickInterface, testManifestFromJsonOneAppOneScope)
505{
506 Manifest m = manifest_from_json(FAKE_JSON_MANIFEST_ONE_APP_ONE_SCOPE);
507 ASSERT_EQ(m.first_app_name, "fake-app");
508 ASSERT_EQ(m.first_scope_id, "com.example.fake-1app-1scope_fake-scope-hook");
509 ASSERT_TRUE(m.has_any_apps());
510 ASSERT_TRUE(m.has_any_scopes());
511}
512
513TEST(ClickInterface, testManifestFromJsonTwoAppsTwoScopes)
514{
515 Manifest m = manifest_from_json(FAKE_JSON_MANIFEST_TWO_APPS_TWO_SCOPES);
516 ASSERT_EQ(m.first_app_name, "fake-app1");
517 ASSERT_EQ(m.first_scope_id, "com.example.fake-2apps-2scopes_fake-scope-hook1");
518 ASSERT_TRUE(m.has_any_apps());
519 ASSERT_TRUE(m.has_any_scopes());
520}
521
522TEST_F(ClickInterfaceTest, testGetManifestForAppParseError)
523{
524 FakeClickInterface iface;
525 EXPECT_CALL(iface, get_manifest_json(_)).
526 Times(1).
527 WillOnce(Return("INVALID JSON"));
528 EXPECT_CALL(*this, manifest_callback(_, InterfaceError::ParseError));
529 iface.get_manifest_for_app(FAKE_PACKAGENAME, [this](Manifest manifest,
530 InterfaceError error){
531 manifest_callback(manifest, error);
532 });
533}
534
535TEST_F(ClickInterfaceTest, testGetManifestForAppIsRemovable)
536{
537 FakeClickInterface iface;
538 EXPECT_CALL(iface, get_manifest_json(_)).
539 Times(1).
540 WillOnce(Return(FAKE_JSON_MANIFEST_REMOVABLE));
541 iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest manifest,
542 InterfaceError error){
543 ASSERT_TRUE(error == InterfaceError::NoError);
544 ASSERT_TRUE(manifest.removable);
545 });
546}
547
548TEST_F(ClickInterfaceTest, testGetManifestForAppIsNotRemovable)
549{
550 FakeClickInterface iface;
551 EXPECT_CALL(iface, get_manifest_json(_)).
552 Times(1).
553 WillOnce(Return(FAKE_JSON_MANIFEST_NONREMOVABLE));
554 iface.get_manifest_for_app(FAKE_PACKAGENAME, [](Manifest manifest,
555 InterfaceError error){
556 ASSERT_TRUE(error == InterfaceError::NoError);
557 ASSERT_FALSE(manifest.removable);
558 });
559}
560
561TEST_F(ClickInterfaceTest, testGetInstalledPackagesParsed)487TEST_F(ClickInterfaceTest, testGetInstalledPackagesParsed)
562{488{
563 FakeClickInterface iface;489 FakeClickInterface iface;
564490
=== modified file 'libclickscope/tests/test_preview.cpp'
--- libclickscope/tests/test_preview.cpp 2016-12-02 18:37:59 +0000
+++ libclickscope/tests/test_preview.cpp 2017-01-10 16:06:37 +0000
@@ -31,9 +31,7 @@
3131
32#include <click/index.h>32#include <click/index.h>
33#include <click/interface.h>33#include <click/interface.h>
34#include <click/reviews.h>
35#include <fake_json.h>34#include <fake_json.h>
36#include <mock_ubuntu_download_manager.h>
3735
38#include <QCoreApplication>36#include <QCoreApplication>
39#include <QTimer>37#include <QTimer>
@@ -70,26 +68,12 @@
7068
71};69};
7270
73class FakeReviews : public click::Reviews
74{
75public:
76 FakeReviews() {
77
78 }
79
80 click::web::Cancellable fetch_reviews(const std::string &/*package_name*/, std::function<void (click::ReviewList, Error)> callback, bool) override {
81 callback(click::ReviewList(), Error::NoError);
82 return click::web::Cancellable();
83 }
84};
85
86class FakePreview : public click::PreviewStrategy71class FakePreview : public click::PreviewStrategy
87{72{
88public:73public:
89 FakePreview(Result& result) : click::PreviewStrategy::PreviewStrategy(result)74 FakePreview(Result& result) : click::PreviewStrategy::PreviewStrategy(result)
90 {75 {
91 index.reset(new FakeIndex());76 index.reset(new FakeIndex());
92 reviews.reset(new FakeReviews());
93 }77 }
9478
95 void run(const PreviewReplyProxy &/*reply*/)79 void run(const PreviewReplyProxy &/*reply*/)
@@ -155,8 +139,6 @@
155 FakePreview preview{result};139 FakePreview preview{result};
156 preview.populateDetails(140 preview.populateDetails(
157 [](const click::PackageDetails &){141 [](const click::PackageDetails &){
158 },
159 [](const click::ReviewList&, click::Reviews::Error){
160 });142 });
161143
162}144}
@@ -342,150 +324,6 @@
342 ASSERT_EQ(expected_order, preview.call_order);324 ASSERT_EQ(expected_order, preview.call_order);
343}325}
344326
345class StrategyChooserTest : public Test {
346protected:
347 unity::scopes::testing::Result result;
348 unity::scopes::ActionMetadata metadata;
349 unity::scopes::VariantMap metadict;
350 QSharedPointer<click::web::Client> client;
351 QSharedPointer<MockSystemDownloadManager> dm;
352 std::shared_ptr<click::DepartmentsDb> depts;
353 const std::string FAKE_SHA512 = "FAKE_SHA512";
354
355public:
356 StrategyChooserTest() : metadata("en_EN", "phone") {
357 }
358};
359
360class MockablePreview : public click::Preview {
361public:
362 MockablePreview(const unity::scopes::Result& result, const unity::scopes::ActionMetadata& metadata) :
363 click::Preview(result, metadata)
364 {
365
366 }
367
368 MOCK_METHOD6(build_installing,
369 click::PreviewStrategy*(const std::string&,
370 const std::string&,
371 const unity::scopes::Result&,
372 const QSharedPointer<click::web::Client>&,
373 const QSharedPointer<Ubuntu::DownloadManager::Manager>&,
374 std::shared_ptr<click::DepartmentsDb>));
375};
376
377TEST_F(StrategyChooserTest, testSha512IsUsed) {
378 metadict["action_id"] = click::Preview::Actions::INSTALL_CLICK;
379 metadict["download_url"] = "fake_download_url";
380 metadict["download_sha512"] = FAKE_SHA512;
381 metadata.set_scope_data(unity::scopes::Variant(metadict));
382 MockablePreview preview(result, metadata);
383 EXPECT_CALL(preview, build_installing(_, FAKE_SHA512, _, _, _, _));
384 preview.choose_strategy(client, dm, depts);
385}
386
387
388class UninstalledPreviewTest : public PreviewsBaseTest {
389public:
390 FakeResult result{vm};
391 click::PackageDetails details;
392 unity::scopes::PreviewWidgetList widgets;
393 QSharedPointer<click::web::Client> client;
394 QSharedPointer<MockSystemDownloadManager> sdm;
395 std::shared_ptr<click::DepartmentsDb> depts;
396 unity::scopes::testing::MockPreviewReply reply;
397 std::shared_ptr<unity::scopes::testing::MockPreviewReply> replyptr{&reply, [](unity::scopes::testing::MockPreviewReply*){}};
398};
399
400class FakeBaseUninstalledPreview : public click::UninstalledPreview {
401 std::string object_path;
402public:
403 FakeBaseUninstalledPreview(const std::string& object_path,
404 const unity::scopes::Result& result,
405 const unity::scopes::ActionMetadata& metadata,
406 const QSharedPointer<click::web::Client>& client,
407 const std::shared_ptr<click::DepartmentsDb>& depts,
408 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager)
409 : click::UninstalledPreview(result, metadata, client, depts, manager),
410 object_path(object_path)
411 {
412 }
413
414 void populateDetails(std::function<void (const click::PackageDetails &)> details_callback,
415 std::function<void (const click::ReviewList &, click::Reviews::Error)> reviews_callback) {
416 click::PackageDetails details;
417 details_callback(details);
418 reviews_callback({}, click::Reviews::Error::NoError);
419 }
420};
421
422class FakeUninstalledPreview : public FakeBaseUninstalledPreview {
423public:
424 MOCK_METHOD1(uninstalledActionButtonWidgets, scopes::PreviewWidgetList (const click::PackageDetails &details));
425 MOCK_METHOD1(progressBarWidget, scopes::PreviewWidgetList(const std::string& object_path));
426 FakeUninstalledPreview(const std::string& object_path,
427 const unity::scopes::Result& result,
428 const unity::scopes::ActionMetadata& metadata,
429 const QSharedPointer<click::web::Client>& client,
430 const std::shared_ptr<click::DepartmentsDb>& depts,
431 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager)
432 : FakeBaseUninstalledPreview(object_path, result, metadata, client, depts, manager) {
433 }
434};
435
436
437// FIXME: Needs Qt main loop
438TEST_F(UninstalledPreviewTest, DISABLED_testDownloadInProgress) {
439 std::string fake_object_path = "/fake/object/path";
440
441 result["name"] = "fake_app_name";
442 scopes::PreviewWidgetList response;
443 unity::scopes::ActionMetadata metadata("en_EN", "desktop");
444 FakeUninstalledPreview preview(fake_object_path, result, metadata, client, depts, sdm);
445 EXPECT_CALL(preview, progressBarWidget(_))
446 .Times(1)
447 .WillOnce(Return(response));
448 EXPECT_CALL(*replyptr, register_layout(_));
449 preview.run(replyptr);
450}
451
452// FIXME: Needs Qt main loop
453TEST_F(UninstalledPreviewTest, DISABLED_testNoDownloadProgress) {
454 std::string fake_object_path = "";
455
456 result["name"] = "fake_app_name";
457 scopes::PreviewWidgetList response;
458 unity::scopes::ActionMetadata metadata("en_EN", "desktop");
459 FakeUninstalledPreview preview(fake_object_path, result, metadata, client, depts, sdm);
460 EXPECT_CALL(preview, uninstalledActionButtonWidgets(_))
461 .Times(1)
462 .WillOnce(Return(response));
463 preview.run(replyptr);
464}
465
466class FakeUninstalledRefundablePreview : FakeBaseUninstalledPreview {
467public:
468 FakeUninstalledRefundablePreview(const unity::scopes::Result& result,
469 const unity::scopes::ActionMetadata& metadata,
470 const QSharedPointer<click::web::Client>& client,
471 const std::shared_ptr<click::DepartmentsDb>& depts,
472 const QSharedPointer<Ubuntu::DownloadManager::Manager>& manager)
473 : FakeBaseUninstalledPreview(std::string{""}, result, metadata, client, depts, manager){
474 }
475 using click::UninstalledPreview::uninstalledActionButtonWidgets;
476};
477
478unity::scopes::VariantArray get_actions_from_widgets(const unity::scopes::PreviewWidgetList& widgets, int widget_number) {
479 auto widget = *std::next(widgets.begin(), widget_number);
480 return widget.attribute_values()["actions"].get_array();
481}
482
483std::string get_action_from_widgets(const unity::scopes::PreviewWidgetList& widgets, int widget_number, int action_number) {
484 auto actions = get_actions_from_widgets(widgets, widget_number);
485 auto selected_action = actions.at(action_number).get_dict();
486 return selected_action["id"].get_string();
487}
488
489class InstalledPreviewTest : public Test {327class InstalledPreviewTest : public Test {
490protected:328protected:
491 unity::scopes::testing::Result result;329 unity::scopes::testing::Result result;
@@ -499,25 +337,6 @@
499 }337 }
500};338};
501339
502TEST_F(InstalledPreviewTest, testReviewWidgetIsNew) {
503 click::InstalledPreview preview(result, metadata, client, depts);
504 click::Review existing_review;
505 existing_review.id = 0;
506 auto widget = preview.createRatingWidget(existing_review);
507 ASSERT_EQ(widget.widget_type(), "rating-input");
508}
509
510TEST_F(InstalledPreviewTest, testReviewWidgetIsEdit) {
511 click::InstalledPreview preview(result, metadata, client, depts);
512 click::Review existing_review;
513 existing_review.id = 123456789;
514 existing_review.rating = 2.625f;
515 existing_review.review_text = "Mediocre at best.";
516 existing_review.reviewer_name = "reviewbot";
517 auto widget = preview.createRatingWidget(existing_review);
518 ASSERT_EQ(widget.widget_type(), "rating-edit");
519}
520
521TEST_F(InstalledPreviewTest, testGetApplicationURIClick) {340TEST_F(InstalledPreviewTest, testGetApplicationURIClick) {
522 click::InstalledPreview preview(result, metadata, client, depts);341 click::InstalledPreview preview(result, metadata, client, depts);
523 click::Manifest manifest;342 click::Manifest manifest;
524343
=== removed file 'libclickscope/tests/test_reviews.cpp'
--- libclickscope/tests/test_reviews.cpp 2016-12-02 18:37:59 +0000
+++ libclickscope/tests/test_reviews.cpp 1970-01-01 00:00:00 +0000
@@ -1,487 +0,0 @@
1/*
2 * Copyright (C) 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * In addition, as a special exception, the copyright holders give
17 * permission to link the code of portions of this program with the
18 * OpenSSL library under certain conditions as described in each
19 * individual source file, and distribute linked combinations
20 * including the two.
21 * You must obey the GNU General Public License in all respects
22 * for all of the code used other than OpenSSL. If you modify
23 * file(s) with this exception, you may extend this exception to your
24 * version of the file(s), but you are not obligated to do so. If you
25 * do not wish to do so, delete this exception statement from your
26 * version. If you delete this exception statement from all source
27 * files in the program, then also delete it here.
28 */
29
30#include <click/configuration.h>
31#include <click/reviews.h>
32#include <click/webclient.h>
33
34#include <tests/mock_network_access_manager.h>
35#include <tests/mock_ubuntuone_credentials.h>
36#include <tests/mock_webclient.h>
37
38#include "fake_json.h"
39
40#include <gtest/gtest.h>
41#include <memory>
42#include <stdlib.h>
43
44using namespace ::testing;
45
46namespace
47{
48
49class ReviewsTest : public ::testing::Test {
50protected:
51 QSharedPointer<MockClient> clientPtr;
52 QSharedPointer<MockNetworkAccessManager> namPtr;
53 std::shared_ptr<click::Reviews> reviewsPtr;
54
55 virtual void SetUp() {
56 namPtr.reset(new MockNetworkAccessManager());
57 clientPtr.reset(new NiceMock<MockClient>(namPtr));
58 reviewsPtr.reset(new click::Reviews(clientPtr));
59 }
60
61public:
62 MOCK_METHOD2(reviews_callback, void(click::ReviewList, click::Reviews::Error));
63};
64}
65
66TEST_F(ReviewsTest, bringToFrontUserMatches)
67{
68 click::Review r1;
69 r1.id = 1;
70 r1.reviewer_username = "user1";
71
72 click::Review r2;
73 r2.id = 2;
74 r2.reviewer_username = "user2";
75
76 click::Review r3;
77 r3.id = 3;
78 r3.reviewer_username = "user3";
79
80 click::ReviewList reviews {r1, r2, r3};
81
82 auto newReviews = bring_to_front(reviews, "user2");
83 EXPECT_EQ(3u, newReviews.size());
84 auto it = newReviews.begin();
85 EXPECT_EQ(2u, (*it).id);
86 ++it;
87 EXPECT_EQ(1u, (*it).id);
88 ++it;
89 EXPECT_EQ(3u, (*it).id);
90}
91
92TEST_F(ReviewsTest, bringToFrontUserMatchesFirstElement)
93{
94 click::Review r1;
95 r1.id = 1;
96 r1.reviewer_username = "user1";
97
98 click::Review r2;
99 r2.id = 2;
100 r2.reviewer_username = "user2";
101
102 click::ReviewList reviews {r1, r2};
103
104 auto newReviews = bring_to_front(reviews, "user1");
105 EXPECT_EQ(2u, newReviews.size());
106 auto it = newReviews.begin();
107 EXPECT_EQ(1u, (*it).id);
108 ++it;
109 EXPECT_EQ(2u, (*it).id);
110}
111
112TEST_F(ReviewsTest, bringToFrontEmptyList)
113{
114 click::ReviewList reviews;
115
116 auto newReviews = bring_to_front(reviews, "user1");
117 EXPECT_EQ(0u, newReviews.size());
118}
119
120TEST_F(ReviewsTest, bringToFrontUserDoesntMatch)
121{
122 click::Review r1;
123 r1.id = 1;
124 r1.reviewer_username = "user1";
125
126 click::Review r2;
127 r2.id = 2;
128 r2.reviewer_username = "user2";
129
130 click::ReviewList reviews {r1, r2};
131
132 auto newReviews = bring_to_front(reviews, "user0");
133 EXPECT_EQ(2u, newReviews.size());
134 auto it = newReviews.begin();
135 EXPECT_EQ(1u, (*it).id);
136 ++it;
137 EXPECT_EQ(2u, (*it).id);
138}
139
140TEST_F(ReviewsTest, testFetchReviewsCallsWebservice)
141{
142 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
143 auto response = responseForReply(reply.asSharedPtr());
144
145 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
146 .Times(1)
147 .WillOnce(Return(response));
148
149 reviewsPtr->fetch_reviews("", [](click::ReviewList,
150 click::Reviews::Error) {});
151}
152
153TEST_F(ReviewsTest, testFetchReviewsDoesNotSignCall)
154{
155 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
156 auto response = responseForReply(reply.asSharedPtr());
157
158 EXPECT_CALL(*clientPtr, callImpl(_, _, false, _, _, _))
159 .Times(1)
160 .WillOnce(Return(response));
161
162 reviewsPtr->fetch_reviews("", [](click::ReviewList,
163 click::Reviews::Error) {});
164}
165
166TEST_F(ReviewsTest, testFetchReviewsSendsQueryAsParam)
167{
168 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
169 auto response = responseForReply(reply.asSharedPtr());
170
171 click::web::CallParams params;
172 params.add(click::REVIEWS_QUERY_ARGNAME, FAKE_PACKAGENAME);
173 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, params))
174 .Times(1)
175 .WillOnce(Return(response));
176
177 reviewsPtr->fetch_reviews(FAKE_PACKAGENAME, [](click::ReviewList,
178 click::Reviews::Error) {});
179}
180
181TEST_F(ReviewsTest, testFetchReviewsSendsCorrectPath)
182{
183 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
184 auto response = responseForReply(reply.asSharedPtr());
185
186 EXPECT_CALL(*clientPtr, callImpl(EndsWith(click::REVIEWS_API_PATH),
187 _, _, _, _, _))
188 .Times(1)
189 .WillOnce(Return(response));
190
191 reviewsPtr->fetch_reviews(FAKE_PACKAGENAME, [](click::ReviewList,
192 click::Reviews::Error) {});
193}
194
195TEST_F(ReviewsTest, testFetchReviewsCallbackCalled)
196{
197 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
198 auto response = responseForReply(reply.asSharedPtr());
199
200 QByteArray fake_json("[]");
201 EXPECT_CALL(reply.instance, readAll())
202 .Times(1)
203 .WillOnce(Return(fake_json));
204 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
205 .Times(1)
206 .WillOnce(Return(response));
207 EXPECT_CALL(*this, reviews_callback(_, _)).Times(1);
208
209 reviewsPtr->fetch_reviews("", [this](click::ReviewList reviews,
210 click::Reviews::Error error){
211 reviews_callback(reviews, error);
212 });
213 response->replyFinished();
214}
215
216TEST_F(ReviewsTest, testFetchReviewsNot200)
217{
218 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
219 auto response = responseForReply(reply.asSharedPtr());
220
221 EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(301)));
222 EXPECT_CALL(reply.instance, readAll())
223 .Times(1)
224 .WillOnce(Return(FAKE_JSON_REVIEWS_RESULT_ONE.c_str()));
225 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
226 .Times(1)
227 .WillOnce(Return(response));
228 click::ReviewList empty_reviews_list;
229 EXPECT_CALL(*this, reviews_callback(empty_reviews_list, _)).Times(1);
230
231 reviewsPtr->fetch_reviews("", [this](click::ReviewList reviews,
232 click::Reviews::Error error){
233 reviews_callback(reviews, error);
234 });
235 response->replyFinished();
236}
237
238TEST_F(ReviewsTest, testFetchReviewsEmptyJsonIsParsed)
239{
240 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
241 auto response = responseForReply(reply.asSharedPtr());
242
243 QByteArray fake_json("[]");
244 EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(200)));
245 EXPECT_CALL(reply.instance, readAll())
246 .Times(1)
247 .WillOnce(Return(fake_json));
248 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
249 .Times(1)
250 .WillOnce(Return(response));
251 click::ReviewList empty_reviews_list;
252 EXPECT_CALL(*this, reviews_callback(empty_reviews_list, _)).Times(1);
253
254 reviewsPtr->fetch_reviews("", [this](click::ReviewList reviews,
255 click::Reviews::Error error){
256 reviews_callback(reviews, error);
257 });
258 response->replyFinished();
259}
260
261TEST_F(ReviewsTest, testFetchReviewsSingleJsonIsParsed)
262{
263 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
264 auto response = responseForReply(reply.asSharedPtr());
265
266 QByteArray fake_json(FAKE_JSON_REVIEWS_RESULT_ONE.c_str());
267 EXPECT_CALL(reply.instance, attribute(_)).WillOnce(Return(QVariant(200)));
268 EXPECT_CALL(reply.instance, readAll())
269 .Times(1)
270 .WillOnce(Return(fake_json));
271 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
272 .Times(1)
273 .WillOnce(Return(response));
274 click::ReviewList single_review_list =
275 {
276 click::Review
277 {
278 1, 4, 0, 0, false,
279 "2014-01-28T09:09:47.218Z", "null",
280 FAKE_PACKAGENAME, "0.2",
281 "en",
282 "Review Summary", "It is ok.",
283 "Reviewer", "reviewer"
284 }
285 };
286 EXPECT_CALL(*this, reviews_callback(single_review_list, _)).Times(1);
287
288 reviewsPtr->fetch_reviews("", [this](click::ReviewList reviews,
289 click::Reviews::Error error){
290 reviews_callback(reviews, error);
291 });
292 response->replyFinished();
293}
294
295TEST_F(ReviewsTest, testFetchReviewsNetworkErrorReported)
296{
297 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
298 auto response = responseForReply(reply.asSharedPtr());
299
300 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
301 .Times(1)
302 .WillOnce(Return(response));
303 EXPECT_CALL(reply.instance, errorString())
304 .Times(1)
305 .WillOnce(Return("fake error"));
306 reviewsPtr->fetch_reviews("", [this](click::ReviewList reviews,
307 click::Reviews::Error error){
308 reviews_callback(reviews, error);
309 });
310 click::ReviewList empty_reviews_list;
311 EXPECT_CALL(*this, reviews_callback(empty_reviews_list,
312 click::Reviews::Error::NetworkError))
313 .Times(1);
314
315 emit reply.instance.error(QNetworkReply::UnknownNetworkError);
316}
317
318TEST_F(ReviewsTest, testFetchReviewsIsCancellable)
319{
320 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
321 auto response = responseForReply(reply.asSharedPtr());
322
323 EXPECT_CALL(*clientPtr, callImpl(_, _, _, _, _, _))
324 .Times(1)
325 .WillOnce(Return(response));
326
327 auto fetch_reviews_op = reviewsPtr->fetch_reviews("", [](click::ReviewList,
328 click::Reviews::Error) {});
329 EXPECT_CALL(reply.instance, abort()).Times(1);
330 fetch_reviews_op.cancel();
331}
332
333TEST_F(ReviewsTest, testSubmitReviewIsCancellable)
334{
335 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
336 auto response = responseForReply(reply.asSharedPtr());
337
338 click::Review review;
339 review.rating = 3;
340 review.review_text = "A review";
341 review.package_name = "com.example.test";
342 review.package_version = "0.1";
343
344 EXPECT_CALL(*clientPtr, callImpl(_, "POST", true, _, _, _))
345 .Times(1)
346 .WillOnce(Return(response));
347
348 auto submit_op = reviewsPtr->submit_review(review,
349 [](click::Reviews::Error){});
350 EXPECT_CALL(reply.instance, abort()).Times(1);
351 submit_op.cancel();
352}
353
354TEST_F(ReviewsTest, testSubmitReviewUtf8)
355{
356 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
357 auto response = responseForReply(reply.asSharedPtr());
358
359 click::Review review;
360 review.rating = 3;
361 review.review_text = "'\"小海嚴選";
362 review.package_name = "com.example.test";
363 review.package_version = "0.1";
364
365 // NOTE: gmock replaces the \" above as \\\" for HasSubstr(), so we have
366 // to manually copy the string into the expected result.
367 std::string expected_review_text = "\"review_text\":\"'\\\"小海嚴選\"";
368
369 EXPECT_CALL(*clientPtr, callImpl(_, "POST", true, _,
370 HasSubstr(expected_review_text), _))
371 .Times(1)
372 .WillOnce(Return(response));
373
374 auto submit_op = reviewsPtr->submit_review(review,
375 [](click::Reviews::Error){});
376}
377
378TEST_F(ReviewsTest, testSubmitReviewLanguageCorrect)
379{
380 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
381 auto response = responseForReply(reply.asSharedPtr());
382
383 click::Review review;
384 review.rating = 3;
385 review.review_text = "A review.";
386 review.package_name = "com.example.test";
387 review.package_version = "0.1";
388
389 ASSERT_EQ(setenv(click::Configuration::LANGUAGE_ENVVAR,
390 "es_AR.UTF-8", 1), 0);
391 std::string expected_language = "\"language\":\"es\"";
392 EXPECT_CALL(*clientPtr, callImpl(_, "POST", true, _,
393 HasSubstr(expected_language), _))
394 .Times(1)
395 .WillOnce(Return(response));
396
397 auto submit_op = reviewsPtr->submit_review(review,
398 [](click::Reviews::Error){});
399 ASSERT_EQ(unsetenv(click::Configuration::LANGUAGE_ENVVAR), 0);
400}
401
402TEST_F(ReviewsTest, testSubmitReviewLanguageCorrectForFullLangCodes)
403{
404 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
405 auto response = responseForReply(reply.asSharedPtr());
406
407 click::Review review;
408 review.rating = 3;
409 review.review_text = "A review.";
410 review.package_name = "com.example.test";
411 review.package_version = "0.1";
412
413 for (std::string lang: click::Configuration::FULL_LANG_CODES) {
414 ASSERT_EQ(setenv(click::Configuration::LANGUAGE_ENVVAR,
415 lang.c_str(), 1), 0);
416 std::string expected_language = "\"language\":\"" + lang + "\"";
417 EXPECT_CALL(*clientPtr, callImpl(_, "POST", true, _,
418 HasSubstr(expected_language), _))
419 .Times(1)
420 .WillOnce(Return(response));
421
422 auto submit_op = reviewsPtr->submit_review(review,
423 [](click::Reviews::Error){});
424 ASSERT_EQ(unsetenv(click::Configuration::LANGUAGE_ENVVAR), 0);
425 }
426}
427
428TEST_F(ReviewsTest, testEditReviewUrlHasReviewId)
429{
430 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
431 auto response = responseForReply(reply.asSharedPtr());
432
433 click::Review review;
434 review.id = 1234;
435 review.rating = 4;
436 review.review_text = "A review";
437 review.package_name = "com.example.test";
438 review.package_version = "0.1";
439
440 EXPECT_CALL(*clientPtr, callImpl(HasSubstr("/1234/"), "PUT", true, _, _, _))
441 .Times(1)
442 .WillOnce(Return(response));
443
444 auto submit_op = reviewsPtr->edit_review(review,
445 [](click::Reviews::Error){});
446}
447
448TEST_F(ReviewsTest, testEditReviewIsCancellable)
449{
450 LifetimeHelper<click::network::Reply, MockNetworkReply> reply;
451 auto response = responseForReply(reply.asSharedPtr());
452
453 click::Review review;
454 review.id = 1234;
455 review.rating = 4;
456 review.review_text = "A review";
457 review.package_name = "com.example.test";
458 review.package_version = "0.1";
459
460 EXPECT_CALL(*clientPtr, callImpl(_, "PUT", true, _, _, _))
461 .Times(1)
462 .WillOnce(Return(response));
463
464 auto submit_op = reviewsPtr->edit_review(review,
465 [](click::Reviews::Error){});
466 EXPECT_CALL(reply.instance, abort()).Times(1);
467 submit_op.cancel();
468}
469
470
471TEST_F(ReviewsTest, testGetBaseUrl)
472{
473 const char *value = getenv(click::REVIEWS_BASE_URL_ENVVAR.c_str());
474 if (value != NULL) {
475 ASSERT_TRUE(unsetenv(click::REVIEWS_BASE_URL_ENVVAR.c_str()) == 0);
476 }
477 ASSERT_TRUE(click::Reviews::get_base_url() == click::REVIEWS_BASE_URL);
478
479}
480
481TEST_F(ReviewsTest, testGetBaseUrlFromEnv)
482{
483 ASSERT_TRUE(setenv(click::REVIEWS_BASE_URL_ENVVAR.c_str(),
484 FAKE_SERVER.c_str(), 1) == 0);
485 ASSERT_TRUE(click::Reviews::get_base_url() == FAKE_SERVER);
486 ASSERT_TRUE(unsetenv(click::REVIEWS_BASE_URL_ENVVAR.c_str()) == 0);
487}
4880
=== modified file 'scope/clickapps/apps-scope.cpp'
--- scope/clickapps/apps-scope.cpp 2016-11-08 13:42:04 +0000
+++ scope/clickapps/apps-scope.cpp 2017-01-10 16:06:37 +0000
@@ -81,7 +81,6 @@
81 static const int zero = 0;81 static const int zero = 0;
82 auto emptyCb = [this]()82 auto emptyCb = [this]()
83 {83 {
84 dm.reset(Ubuntu::DownloadManager::Manager::createSessionManager());
85 qt_ready_for_search_p.set_value();84 qt_ready_for_search_p.set_value();
8685
87 sso.reset(new click::CredentialsService());86 sso.reset(new click::CredentialsService());
@@ -107,57 +106,19 @@
107 const unity::scopes::ActionMetadata& metadata) {106 const unity::scopes::ActionMetadata& metadata) {
108 qDebug() << "Scope::preview() called.";107 qDebug() << "Scope::preview() called.";
109 auto preview = new click::Preview(result, metadata, qt_ready_for_preview_f.share());108 auto preview = new click::Preview(result, metadata, qt_ready_for_preview_f.share());
110 preview->choose_strategy(client, dm, depts_db);109 preview->choose_strategy(client, depts_db);
111 return unity::scopes::PreviewQueryBase::UPtr{preview};110 return unity::scopes::PreviewQueryBase::UPtr{preview};
112}111}
113112
114113
115unity::scopes::ActivationQueryBase::UPtr click::Scope::perform_action(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata,114unity::scopes::ActivationQueryBase::UPtr click::Scope::perform_action(unity::scopes::Result const& result, unity::scopes::ActionMetadata const& metadata,
116 std::string const& widget_id, std::string const& action_id)115 std::string const&, std::string const& action_id)
117{116{
118 if (action_id == click::Preview::Actions::CONFIRM_UNINSTALL) {
119 return scopes::ActivationQueryBase::UPtr(new PerformUninstallAction(result, metadata));
120 }
121
122 auto activation = new ScopeActivation(result, metadata);117 auto activation = new ScopeActivation(result, metadata);
123 qDebug() << "perform_action called with action_id" << QString().fromStdString(action_id);118 qDebug() << "perform_action called with action_id" << QString().fromStdString(action_id);
124119
125 if (action_id == click::Preview::Actions::UNINSTALL_CLICK) {120 if (action_id == click::Preview::Actions::SHOW_INSTALLED) {
126 activation->setHint(click::Preview::Actions::UNINSTALL_CLICK, unity::scopes::Variant(true));
127 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
128 } else if (action_id == click::Preview::Actions::CANCEL_PURCHASE_INSTALLED) {
129 activation->setHint(click::Preview::Actions::CANCEL_PURCHASE_INSTALLED, unity::scopes::Variant(true));
130 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
131 } else if (action_id == click::Preview::Actions::CANCEL_PURCHASE_UNINSTALLED) {
132 activation->setHint(click::Preview::Actions::CANCEL_PURCHASE_UNINSTALLED, unity::scopes::Variant(true));
133 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
134 } else if (action_id == click::Preview::Actions::SHOW_INSTALLED) {
135 activation->setHint(click::Preview::Actions::SHOW_INSTALLED, unity::scopes::Variant(true));121 activation->setHint(click::Preview::Actions::SHOW_INSTALLED, unity::scopes::Variant(true));
136 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
137 } else if (action_id == click::Preview::Actions::SHOW_UNINSTALLED) {
138 activation->setHint(click::Preview::Actions::SHOW_UNINSTALLED, unity::scopes::Variant(true));
139 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
140 } else if (action_id == click::Preview::Actions::CONFIRM_CANCEL_PURCHASE_UNINSTALLED) {
141 activation->setHint(click::Preview::Actions::CONFIRM_CANCEL_PURCHASE_UNINSTALLED, unity::scopes::Variant(true));
142 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
143 } else if (action_id == click::Preview::Actions::CONFIRM_CANCEL_PURCHASE_INSTALLED) {
144 activation->setHint(click::Preview::Actions::CONFIRM_CANCEL_PURCHASE_INSTALLED, unity::scopes::Variant(true));
145 activation->setStatus(unity::scopes::ActivationResponse::Status::ShowPreview);
146 } else if (action_id == click::Preview::Actions::RATED) {
147 scopes::VariantMap rating_info = metadata.scope_data().get_dict();
148 // Cast to int because widget gives us double, which is wrong.
149 int rating = ((int)rating_info["rating"].get_double());
150 std::string review_text = rating_info["review"].get_string();
151
152 // We have to get the values and then set them as hints here, to be
153 // able to pass them on to the Preview, which actually makes the
154 // call to submit.
155 activation->setHint("rating", scopes::Variant(rating));
156 activation->setHint("review", scopes::Variant(review_text));
157 activation->setHint(click::Preview::Actions::RATED,
158 scopes::Variant(true));
159 activation->setHint("widget_id", scopes::Variant(widget_id));
160 activation->setStatus(scopes::ActivationResponse::Status::ShowPreview);
161 }122 }
162 return scopes::ActivationQueryBase::UPtr(activation);123 return scopes::ActivationQueryBase::UPtr(activation);
163}124}
164125
=== modified file 'scope/clickapps/apps-scope.h'
--- scope/clickapps/apps-scope.h 2016-10-24 21:26:23 +0000
+++ scope/clickapps/apps-scope.h 2017-01-10 16:06:37 +0000
@@ -34,7 +34,6 @@
34#include <click/network_access_manager.h>34#include <click/network_access_manager.h>
35#include <click/webclient.h>35#include <click/webclient.h>
3636
37#include <ubuntu/download_manager/manager.h>
38#include <unity/scopes/ScopeBase.h>37#include <unity/scopes/ScopeBase.h>
39#include <unity/scopes/QueryBase.h>38#include <unity/scopes/QueryBase.h>
40#include <unity/scopes/ActivationQueryBase.h>39#include <unity/scopes/ActivationQueryBase.h>
@@ -73,7 +72,6 @@
73 QSharedPointer<click::network::AccessManager> nam;72 QSharedPointer<click::network::AccessManager> nam;
74 QSharedPointer<click::web::Client> client;73 QSharedPointer<click::web::Client> client;
75 QSharedPointer<click::Index> index;74 QSharedPointer<click::Index> index;
76 QSharedPointer<Ubuntu::DownloadManager::Manager> dm;
77 QSharedPointer<click::CredentialsService> sso;75 QSharedPointer<click::CredentialsService> sso;
78 std::shared_ptr<click::DepartmentsDb> depts_db;76 std::shared_ptr<click::DepartmentsDb> depts_db;
7977
8078
=== modified file 'scope/tests/test_apps_scope.cpp'
--- scope/tests/test_apps_scope.cpp 2015-11-24 18:23:23 +0000
+++ scope/tests/test_apps_scope.cpp 2017-01-10 16:06:37 +0000
@@ -53,32 +53,6 @@
53 }53 }
54};54};
5555
56TEST_F(AppsScopeTest, DISABLED_testConfirmUninstall)
57{
58 result.set_title("foo");
59 result[click::apps::Query::ResultKeys::NAME] = "foo.name";
60 result[click::apps::Query::ResultKeys::VERSION] = "0.1";
61 auto activation = scope.perform_action(result, metadata, "widget",
62 click::Preview::Actions::CONFIRM_UNINSTALL);
63 auto response = activation->activate();
64}
65
66TEST_F(AppsScopeTest, testCancelPurchaseInstalled)
67{
68 auto activation = scope.perform_action(result, metadata, "button",
69 click::Preview::Actions::CANCEL_PURCHASE_INSTALLED);
70 auto response = activation->activate();
71 EXPECT_TRUE(response.scope_data().get_dict()[click::Preview::Actions::CANCEL_PURCHASE_INSTALLED].get_bool());
72}
73
74TEST_F(AppsScopeTest, testCancelPurchaseUninstalled)
75{
76 auto activation = scope.perform_action(result, metadata, "button",
77 click::Preview::Actions::CANCEL_PURCHASE_UNINSTALLED);
78 auto response = activation->activate();
79 EXPECT_TRUE(response.scope_data().get_dict()[click::Preview::Actions::CANCEL_PURCHASE_UNINSTALLED].get_bool());
80}
81
82TEST_F(AppsScopeTest, testShowInstalled)56TEST_F(AppsScopeTest, testShowInstalled)
83{57{
84 auto activation = scope.perform_action(result, metadata, "button",58 auto activation = scope.perform_action(result, metadata, "button",
@@ -86,43 +60,3 @@
86 auto response = activation->activate();60 auto response = activation->activate();
87 EXPECT_TRUE(response.scope_data().get_dict()[click::Preview::Actions::SHOW_INSTALLED].get_bool());61 EXPECT_TRUE(response.scope_data().get_dict()[click::Preview::Actions::SHOW_INSTALLED].get_bool());
88}62}
89
90TEST_F(AppsScopeTest, testShowUninstalled)
91{
92 auto activation = scope.perform_action(result, metadata, "button",
93 click::Preview::Actions::SHOW_UNINSTALLED);
94 auto response = activation->activate();
95 EXPECT_TRUE(response.scope_data().get_dict()[click::Preview::Actions::SHOW_UNINSTALLED].get_bool());
96}
97
98TEST_F(AppsScopeTest, testConfirmCancelPurchaseUninstalled)
99{
100 auto activation = scope.perform_action(result, metadata, "widget_id",
101 click::Preview::Actions::CONFIRM_CANCEL_PURCHASE_UNINSTALLED);
102 auto response = activation->activate();
103 EXPECT_TRUE(response.scope_data().get_dict()[click::Preview::Actions::CONFIRM_CANCEL_PURCHASE_UNINSTALLED].get_bool());
104}
105
106TEST_F(AppsScopeTest, testConfirmCancelPurcahseInstalled)
107{
108 auto activation = scope.perform_action(result, metadata, "widget_id",
109 click::Preview::Actions::CONFIRM_CANCEL_PURCHASE_INSTALLED);
110 auto response = activation->activate();
111 EXPECT_TRUE(response.scope_data().get_dict()[click::Preview::Actions::CONFIRM_CANCEL_PURCHASE_INSTALLED].get_bool());
112}
113
114TEST_F(AppsScopeTest, testRatingNew)
115{
116 auto activation = scope.perform_action(result, metadata, "rating",
117 click::Preview::Actions::RATED);
118 auto response = activation->activate();
119 EXPECT_EQ("rating", response.scope_data().get_dict()["widget_id"].get_string());
120}
121
122TEST_F(AppsScopeTest, testRatingEdit)
123{
124 auto activation = scope.perform_action(result, metadata, "93345",
125 click::Preview::Actions::RATED);
126 auto response = activation->activate();
127 EXPECT_EQ("93345", response.scope_data().get_dict()["widget_id"].get_string());
128}

Subscribers

People subscribed via source and target branches

to all changes: