Merge lp:~diegosarmentero/ubuntu-system-settings/click-updates into lp:ubuntu-system-settings
- click-updates
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Sebastien Bacher |
Approved revision: | 650 |
Merged at revision: | 667 |
Proposed branch: | lp:~diegosarmentero/ubuntu-system-settings/click-updates |
Merge into: | lp:ubuntu-system-settings |
Diff against target: |
1938 lines (+1323/-57) 28 files modified
debian/control (+4/-0) plugins/system-update/CMakeLists.txt (+18/-3) plugins/system-update/Configuration.qml (+1/-0) plugins/system-update/PageComponent.qml (+89/-22) plugins/system-update/download_tracker.cpp (+137/-0) plugins/system-update/download_tracker.h (+87/-0) plugins/system-update/network/network.cpp (+165/-0) plugins/system-update/network/network.h (+64/-0) plugins/system-update/plugin.cpp (+2/-0) plugins/system-update/system_update.cpp (+5/-1) plugins/system-update/system_update.h (+1/-0) plugins/system-update/update.cpp (+23/-5) plugins/system-update/update.h (+15/-0) plugins/system-update/update_manager.cpp (+179/-18) plugins/system-update/update_manager.h (+45/-0) tests/autopilot/ubuntu_system_settings/tests/__init__.py (+2/-4) tests/autopilot/ubuntu_system_settings/tests/test_system_updates.py (+72/-3) tests/plugins/system-update/CMakeLists.txt (+18/-1) tests/plugins/system-update/click.result (+26/-0) tests/plugins/system-update/fakenetwork.cpp (+51/-0) tests/plugins/system-update/fakenetwork.h (+49/-0) tests/plugins/system-update/fakeprocess.cpp (+63/-0) tests/plugins/system-update/fakeprocess.h (+48/-0) tests/plugins/system-update/fakessoservice.cpp (+16/-0) tests/plugins/system-update/fakessoservice.h (+27/-0) tests/plugins/system-update/fakesystemupdate.cpp (+28/-0) tests/plugins/system-update/fakesystemupdate.h (+58/-0) tests/plugins/system-update/tst_updatemanager.cpp (+30/-0) |
To merge this branch: | bzr merge lp:~diegosarmentero/ubuntu-system-settings/click-updates |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sebastien Bacher (community) | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Iain Lane | Needs Fixing | ||
Review via email: mp+208567@code.launchpad.net |
Commit message
- Add click updates support.
Description of the change
This branch adds click support to System Updates, now system updates is going to show the clicks that needs to be updated along with system updates in the same list.
You can IRL test this using the click updates mock service (Desktop):
https:/
(bzr branch lp:clickupdatemockservice)
Just download that branch, and execute it with: python3 mock_click_
(This requires that you build and install the code from this branch first)
About the code:
The Network files has been added to make requests to the server for:
- Get the new list of apps and versions for the apps i have locally
- Get the download url for an specific app
- Get the click token for the download url, to be able to sign it and access the server with valid credentials for download.
DownloadTracker:
This QML Plugin uses the ubuntu download manager client lib to trigger the downloads, monitor them and send back to the UI information about the progress, and execute the install command when the download ends.
The rest of the code, mostly in PageComponent.qml and update_
PS Jenkins bot (ps-jenkins) wrote : | # |
Sebastien Bacher (seb128) wrote : | # |
Thanks but, as pointed by the CI, that doesn't build, it fails on a missing "#include "fakedownloader.h"" ... where is distributed?
- 637. By Diego Sarmentero
-
fix mention of removed file
Sebastien Bacher (seb128) wrote : | # |
Thanks, that builds fine and I was able to test, some comments from a first round of user testing (didn't review the changes yet, that's quite some code to review):
- could you made the downloads a bit slower, so it let time to interact with the UI/pause the download, etc
- the dropping letter is displayed as "500000kb", shouldn't it adapt its units and displays "0.5Gb" instead?
- if you start with some clicks update and a system update, you get a list of 2 clicks and no indication it's checking for the system image status, you should display a spinner while the checking is happening (maybe only displays the list when you get results from both system and click updates)
- clicking the "install 3 updates" triggers the update, clicks are done before the system one ... the button doesn't change though, that's a bit confusing: 2 installed, 1 downloading and it still states "Install 3 updates", could you check with design if we could do better?
- if you do press the "install 3 updates"/"pause all" button a few time you easily get dbus errors displayed over the "installed" for the already upgraded clicks
- once the download are done, if have a system update and click on "not now", you get back to the UI. If you click on the "download 3 updates" button then you get the "installing" screen
I'm going to try to review the code early next week (if others want to help reviewing that would be welcome)
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:637
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Diego Sarmentero (diegosarmentero) wrote : | # |
> Thanks, that builds fine and I was able to test, some comments from a first
> round of user testing (didn't review the changes yet, that's quite some code
> to review):
>
> - could you made the downloads a bit slower, so it let time to interact with
> the UI/pause the download, etc
>
> - the dropping letter is displayed as "500000kb", shouldn't it adapt its units
> and displays "0.5Gb" instead?
>
> - if you start with some clicks update and a system update, you get a list of
> 2 clicks and no indication it's checking for the system image status, you
> should display a spinner while the checking is happening (maybe only displays
> the list when you get results from both system and click updates)
>
> - clicking the "install 3 updates" triggers the update, clicks are done before
> the system one ... the button doesn't change though, that's a bit confusing: 2
> installed, 1 downloading and it still states "Install 3 updates", could you
> check with design if we could do better?
Done
>
> - if you do press the "install 3 updates"/"pause all" button a few time you
> easily get dbus errors displayed over the "installed" for the already upgraded
> clicks
Couldn't reproduce this.
>
> - once the download are done, if have a system update and click on "not now",
> you get back to the UI. If you click on the "download 3 updates" button then
> you get the "installing" screen
>
>
> I'm going to try to review the code early next week (if others want to help
> reviewing that would be welcome)
Done
Diego Sarmentero (diegosarmentero) wrote : | # |
> Thanks, that builds fine and I was able to test, some comments from a first
> round of user testing (didn't review the changes yet, that's quite some code
> to review):
>
> - could you made the downloads a bit slower, so it let time to interact with
> the UI/pause the download, etc
You can do the download slower because we are using all the real services, but i'll try to add a bigger file in the mock service
>
> - the dropping letter is displayed as "500000kb", shouldn't it adapt its units
> and displays "0.5Gb" instead?
>
> - if you start with some clicks update and a system update, you get a list of
> 2 clicks and no indication it's checking for the system image status, you
> should display a spinner while the checking is happening (maybe only displays
> the list when you get results from both system and click updates)
>
> - clicking the "install 3 updates" triggers the update, clicks are done before
> the system one ... the button doesn't change though, that's a bit confusing: 2
> installed, 1 downloading and it still states "Install 3 updates", could you
> check with design if we could do better?
>
> - if you do press the "install 3 updates"/"pause all" button a few time you
> easily get dbus errors displayed over the "installed" for the already upgraded
> clicks
>
> - once the download are done, if have a system update and click on "not now",
> you get back to the UI. If you click on the "download 3 updates" button then
> you get the "installing" screen
>
>
> I'm going to try to review the code early next week (if others want to help
> reviewing that would be welcome)
- 638. By Diego Sarmentero
-
fixing branch as requested
- 639. By Diego Sarmentero
-
adding object names
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:639
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 640. By Diego Sarmentero
-
[ Sebastien Bacher ]
* license: use Label widget instead of Text, it looks more integrated
(LP: #1286262)
* language: don't display an chevron for the language item, the list
displayed is a sheet widget and not a page stack one. (lp: #1289287)
(LP: #1289287)
[ Iain Lane ]
* background selector: lock the toolbar open, per the design (LP:
#1288361)
* Don't crash if the migration script can't set values (LP: #1288833)
[ Michael Terry ]
* Tweak some of the wording of the wizard, and start the language
combo expanded
[ CI bot ]
* Resync trunk
[ Omer Akram ]
* autopilot tests code: fix pep8 and pyflakes warnings. add tests to
make sure we don't regress on pep8/pyflakes .
[ Didier Roche ]
* switch to suru icon theme
[ CI bot ]
* Resync trunk
[ Iain Lane ]
* Also store the ringtone, messages and silent mode settings in
AccountsService. (LP: #1265528)
[ Michael Terry ]
* Add disabled skeleton of a "Welcome to Ubuntu" wizard for first-time
boot. Will be enabled when it is more complete.
[ CI bot ]
* Resync trunk
[ Andrea Cimitan ]
* Add disabled skeleton of a "Welcome to Ubuntu" wizard for first-time
boot. Will be enabled when it is more complete.
[ Iain Lane ]
* Add a 'downloading' parameter to updateAvailableFound so that the UI
can adjust itself. We need to know if a download is already in
progress when we enter the update screen to display 'pause' or
'install' as appropriate.
[ Sebastien Bacher ]
* Workarount qt bug that could lead to non working scrolling
[ Iain Lane ]
* Re-enable updates on the main screen
[ Diego Sarmentero ]
* Avoid conflicts between concurrent calls to checkForUpdates ( (LP:
#1279006)
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:640
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 641. By Diego Sarmentero
-
fixed signal
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:641
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 642. By Diego Sarmentero
-
fixing pep8
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:642
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 643. By Diego Sarmentero
-
fixing lint
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:643
http://
Executed test runs:
SUCCESS: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 644. By Diego Sarmentero
-
adding autopilot tests
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:644
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 645. By Diego Sarmentero
-
autopilot tests complete
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:645
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Diego Sarmentero (diegosarmentero) wrote : | # |
This failures seems to be jenkins related, not an issue with the branch.
- 646. By Diego Sarmentero
-
avoid checking for real updates during tests
Sebastien Bacher (seb128) wrote : | # |
Thanks for the work, that looks good!
Some small issues:
* the CI issue is real (happen on touch devices as well), Omer suggested that fix, http://
* the install tests seem to fail if you have outdated click installed on the system, could you ignore those as you did for the system updates?
* I managed to land in a case where the button at the top was hidden but available updates were still in the list, is that supposed to happen?
I think I ended up there by doing
- open the panel
- the list had 3 clicks to update
- click on one to start download
- use the button at the top to pause/restart downloads
- pause some of the individual downloads
the install finished for the unpaused one and the button vanished
* if you enter the panel and have no credential, click on the link to add an UbuntuOne account, then go back, the label still state that there is an auth issue and there is no way to tell it to refresh
* there is quite some code there, I didn't do a detailled review but from an easy reading things seem to be good!
Sebastien Bacher (seb128) wrote : | # |
oh, another small one, since the "click" binary is used by the new code debian/control should probably have a depends or recommends on "click"
- 647. By Diego Sarmentero
-
improves in tests
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:646
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Sebastien Bacher (seb128) wrote : | # |
Thanks, the CI is still slightly unhappy though, I'm going to test that tomorrow
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:647
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Iain Lane (laney) wrote : | # |
Cheers, looks mostly good*, just some small-ish comments.
119 + function open_online_
120 + Qt.openUrlExter
121 + }
Don't you want to push the page component there? Although this panel does
something weird so doesn't that work?
342 + * Copyright (C) 2013 - Canonical Ltd.
2014 (& other files)
1001 + // PROCESS
1002 + QObject:
1003 + this, SLOT(processOut
remove &(parens) please
I think you ought to be able to use the new libclick instead of executing the
process directly. cjwatson was working on converting the similar use in the
about panel - perhaps he could share his code.
* I couldn't test it though - the mock doesn't work on the phone for me and on my desktop I just get 'software up to date' and this on console
2014-03-20 12:38:20,293 - CRITICAL - ../../.
Alberto Mardegan (mardy) wrote : | # |
On 03/20/2014 02:48 PM, Iain Lane wrote:
> * I couldn't test it though - the mock doesn't work on the phone for me and on my desktop I just get 'software up to date' and this on console
>
> 2014-03-20 12:38:20,293 - CRITICAL - ../../.
This is harmless, I need to lower it to a simple DEBUG.
- 648. By Diego Sarmentero
-
improves in tests and adding click dependency
Diego Sarmentero (diegosarmentero) wrote : | # |
> oh, another small one, since the "click" binary is used by the new code
> debian/control should probably have a depends or recommends on "click"
Done
Diego Sarmentero (diegosarmentero) wrote : | # |
> Thanks for the work, that looks good!
>
> Some small issues:
>
> * the CI issue is real (happen on touch devices as well), Omer suggested that
> fix, http://
Done
>
> * the install tests seem to fail if you have outdated click installed on the
> system, could you ignore those as you did for the system updates?
Done
>
> * I managed to land in a case where the button at the top was hidden but
> available updates were still in the list, is that supposed to happen?
>
> I think I ended up there by doing
> - open the panel
> - the list had 3 clicks to update
> - click on one to start download
> - use the button at the top to pause/restart downloads
> - pause some of the individual downloads
>
> the install finished for the unpaused one and the button vanished
Could not reproduce this.
>
> * if you enter the panel and have no credential, click on the link to add an
> UbuntuOne account, then go back, the label still state that there is an auth
> issue and there is no way to tell it to refresh
It seems System Settings is not refreshing the pages on going back, I assume this, because it can not be reproduced on desktop, on desktop you need to go back to online accounts, and then go back to updates and that works.
>
> * there is quite some code there, I didn't do a detailled review but from an
> easy reading things seem to be good!
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:648
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:648
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
FAILURE: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Sebastien Bacher (seb128) wrote : | # |
The panel seems mostly fine, we should be able to land it this week but we need to resolve first the remaining failing tests (CI is still red). Diego, could you have a look to that and to the review comments from Laney?
- 649. By Diego Sarmentero
-
apply fixes requested
- 650. By Diego Sarmentero
-
fix autopilot tests
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:650
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Diego Sarmentero (diegosarmentero) wrote : | # |
> The panel seems mostly fine, we should be able to land it this week but we
> need to resolve first the remaining failing tests (CI is still red). Diego,
> could you have a look to that and to the review comments from Laney?
Done
Diego Sarmentero (diegosarmentero) wrote : | # |
> Cheers, looks mostly good*, just some small-ish comments.
>
> 119 + function open_online_
> 120 + Qt.openUrlExter
> 121 + }
>
> Don't you want to push the page component there? Although this panel does
> something weird so doesn't that work?
Push wasn't working from the system updates page.
>
> 342 + * Copyright (C) 2013 - Canonical Ltd.
>
> 2014 (& other files)
Done
>
> 1001 + // PROCESS
> 1002 + QObject:
> 1003 + this, SLOT(processOut
>
> remove &(parens) please
Done
>
> I think you ought to be able to use the new libclick instead of executing the
> process directly. cjwatson was working on converting the similar use in the
> about panel - perhaps he could share his code.
I prefer to change this in a future branch, because changing it right now will involve to modify some of the tests and keep delaying this branch with more changes.
>
> * I couldn't test it though - the mock doesn't work on the phone for me and on
> my desktop I just get 'software up to date' and this on console
>
> 2014-03-20 12:38:20,293 - CRITICAL - ../../.
> manager.cpp 106 setupSocketConn
> QDBusError(
> socket /run/user/
Sebastien Bacher (seb128) wrote : | # |
Hum, now 6 tests fails on the phone (the ubuntu_
Traceback (most recent call last):
File "/usr/lib/
super(SystemUpd
File "/usr/lib/
self.pointer.
AttributeError: 'Pointer' object has no attribute 'scroll_
Sebastien Bacher (seb128) wrote : | # |
sorry, ignore the previous comment, the system upgrade I did overwrote the local install of the new version...
Looks good to me, let's get in a silo and try to land it
Preview Diff
1 | === modified file 'debian/control' |
2 | --- debian/control 2014-03-17 22:12:26 +0000 |
3 | +++ debian/control 2014-03-27 13:16:48 +0000 |
4 | @@ -22,6 +22,9 @@ |
5 | qtbase5-dev, |
6 | qtdeclarative5-dev, |
7 | libapt-pkg-dev, |
8 | + libubuntuoneauth-2.0-dev, |
9 | + libubuntu-download-manager-client-dev, |
10 | + libubuntu-download-manager-common-dev, |
11 | xvfb, |
12 | cmake, |
13 | pep8, |
14 | @@ -55,6 +58,7 @@ |
15 | whoopsie-preferences (>= 0.9), |
16 | libsystemsettings1 (= ${binary:Version}), |
17 | system-image-dbus (>= 0.9), |
18 | + click, |
19 | ubuntu-keyboard-data (>= 0.99.trunk.phablet2+13.10.20131001), |
20 | # for the session-migration script |
21 | python3, |
22 | |
23 | === modified file 'plugins/system-update/CMakeLists.txt' |
24 | --- plugins/system-update/CMakeLists.txt 2014-02-06 15:47:12 +0000 |
25 | +++ plugins/system-update/CMakeLists.txt 2014-03-27 13:16:48 +0000 |
26 | @@ -1,10 +1,25 @@ |
27 | set(QML_SOURCES PageComponent.qml Configuration.qml) |
28 | +SET (CMAKE_AUTOMOC ON) |
29 | |
30 | -add_library(UbuntuUpdatePanel MODULE plugin.h system_update.h update_manager.h update.h plugin.cpp system_update.cpp update_manager.cpp update.cpp |
31 | +add_library(UbuntuUpdatePanel MODULE plugin.h system_update.h update_manager.h update.h |
32 | +network/network.h download_tracker.h plugin.cpp system_update.cpp update_manager.cpp |
33 | +update.cpp network/network.cpp download_tracker.cpp |
34 | ${QML_SOURCES}) |
35 | -qt5_use_modules(UbuntuUpdatePanel Qml Quick DBus) |
36 | + |
37 | +qt5_use_modules(UbuntuUpdatePanel Qml Quick Network DBus) |
38 | include_directories(/usr/include/apt-pkg/) |
39 | -target_link_libraries(UbuntuUpdatePanel apt-pkg) |
40 | + |
41 | +find_package (PkgConfig REQUIRED) |
42 | +pkg_check_modules(UBUNTU_DOWNLOAD_MANAGER_CLIENT REQUIRED ubuntu-download-manager-client) |
43 | +pkg_check_modules(UBUNTU_DOWNLOAD_MANAGER_COMMON REQUIRED ubuntu-download-manager-common) |
44 | +pkg_check_modules(UBUNTUONEAUTH REQUIRED ubuntuoneauth-2.0) |
45 | +add_definitions(${UBUNTUONEAUTH_CFLAGS} ${UBUNTUONEAUTH_CFLAGS_OTHER}) |
46 | +target_link_libraries(UbuntuUpdatePanel |
47 | + apt-pkg |
48 | + ${UBUNTUONEAUTH_LDFLAGS} |
49 | + ${UBUNTU_DOWNLOAD_MANAGER_CLIENT_LDFLAGS} |
50 | + ${UBUNTU_DOWNLOAD_MANAGER_COMMON_LDFLAGS} |
51 | +) |
52 | |
53 | set(PLUG_DIR ${PLUGIN_PRIVATE_MODULE_DIR}/Ubuntu/SystemSettings/Update) |
54 | install(TARGETS UbuntuUpdatePanel DESTINATION ${PLUG_DIR}) |
55 | |
56 | === modified file 'plugins/system-update/Configuration.qml' |
57 | --- plugins/system-update/Configuration.qml 2014-01-24 15:17:32 +0000 |
58 | +++ plugins/system-update/Configuration.qml 2014-03-27 13:16:48 +0000 |
59 | @@ -25,6 +25,7 @@ |
60 | |
61 | ItemPage { |
62 | id: root |
63 | + objectName: "configurationPage" |
64 | property UpdateManager updateManager |
65 | title: i18n.tr("Auto download") |
66 | |
67 | |
68 | === modified file 'plugins/system-update/PageComponent.qml' |
69 | --- plugins/system-update/PageComponent.qml 2014-02-26 11:39:47 +0000 |
70 | +++ plugins/system-update/PageComponent.qml 2014-03-27 13:16:48 +0000 |
71 | @@ -35,6 +35,7 @@ |
72 | title: i18n.tr("Updates") |
73 | |
74 | property bool installAll: false |
75 | + property int updatesAvailable: 0 |
76 | |
77 | DeviceInfo { |
78 | id: deviceInfo |
79 | @@ -78,16 +79,14 @@ |
80 | PropertyChanges { target: notification; visible: false} |
81 | PropertyChanges { target: installAllButton; visible: false} |
82 | PropertyChanges { target: checkForUpdatesArea; visible: true} |
83 | - PropertyChanges { target: notification; visible: false} |
84 | - PropertyChanges { target: updatedNotification; visible: false} |
85 | + PropertyChanges { target: updateNotification; visible: false} |
86 | }, |
87 | State { |
88 | name: "NOUPDATES" |
89 | - PropertyChanges { target: updatedNotification; text: i18n.tr("Software is up to date")} |
90 | - PropertyChanges { target: updatedNotification; visible: true} |
91 | + PropertyChanges { target: updateNotification; text: i18n.tr("Software is up to date")} |
92 | + PropertyChanges { target: updateNotification; visible: true} |
93 | PropertyChanges { target: updateList; visible: false} |
94 | PropertyChanges { target: installAllButton; visible: false} |
95 | - PropertyChanges { target: checkForUpdatesArea; visible: false} |
96 | }, |
97 | State { |
98 | name: "SYSTEMUPDATEFAILED" |
99 | @@ -98,18 +97,31 @@ |
100 | PropertyChanges { target: installingImageUpdate; visible: false} |
101 | PropertyChanges { target: installAllButton; visible: false} |
102 | PropertyChanges { target: checkForUpdatesArea; visible: false} |
103 | - PropertyChanges { target: updatedNotification; visible: false} |
104 | + PropertyChanges { target: updateNotification; visible: false} |
105 | }, |
106 | State { |
107 | name: "UPDATE" |
108 | PropertyChanges { target: notification; visible: false} |
109 | PropertyChanges { target: updateList; visible: true} |
110 | PropertyChanges { target: installAllButton; visible: true} |
111 | - PropertyChanges { target: checkForUpdatesArea; visible: false} |
112 | - PropertyChanges { target: updatedNotification; visible: false} |
113 | + PropertyChanges { target: updateNotification; visible: false} |
114 | + }, |
115 | + State { |
116 | + name: "NOCREDENTIALS" |
117 | + PropertyChanges { target: notification; text: i18n.tr("Please log into your Ubuntu One account.")} |
118 | + PropertyChanges { target: notification; onClicked: root.open_online_accounts() } |
119 | + PropertyChanges { target: notification; progression: true} |
120 | + PropertyChanges { target: notification; visible: true} |
121 | + PropertyChanges { target: updateNotification; text: i18n.tr("Credentials not found")} |
122 | + PropertyChanges { target: updateNotification; visible: true} |
123 | + PropertyChanges { target: installAllButton; visible: false} |
124 | } |
125 | ] |
126 | |
127 | + function open_online_accounts() { |
128 | + Qt.openUrlExternally("settings:///system/online-accounts"); |
129 | + } |
130 | + |
131 | UpdateManager { |
132 | id: updateManager |
133 | objectName: "updateManager" |
134 | @@ -121,6 +133,7 @@ |
135 | |
136 | onUpdateAvailableFound: { |
137 | if (updateManager.model.length > 0) { |
138 | + root.updatesAvailable = updateManager.model.length; |
139 | root.state = "UPDATE"; |
140 | root.installAll = downloading |
141 | } else { |
142 | @@ -129,10 +142,21 @@ |
143 | } |
144 | |
145 | onUpdatesNotFound: { |
146 | - root.state = "NOUPDATES"; |
147 | + if (root.state != "NOCREDENTIALS") { |
148 | + root.state = "NOUPDATES"; |
149 | + } |
150 | + } |
151 | + |
152 | + onCheckFinished: { |
153 | + checkForUpdatesArea.visible = false; |
154 | + } |
155 | + |
156 | + onCredentialsNotFound: { |
157 | + root.state = "NOCREDENTIALS"; |
158 | } |
159 | |
160 | onSystemUpdateDownloaded: { |
161 | + root.updatesAvailable -= 1; |
162 | PopupUtils.open(dialogInstallComponent); |
163 | } |
164 | |
165 | @@ -197,7 +221,7 @@ |
166 | id: installAllButton |
167 | objectName: "installAllButton" |
168 | |
169 | - property string primaryText: i18n.tr("Install %1 update", "Install %1 updates", updateManager.model.length).arg(updateManager.model.length) |
170 | + property string primaryText: i18n.tr("Install %1 update", "Install %1 updates", root.updatesAvailable).arg(root.updatesAvailable) |
171 | property string secondaryText: i18n.tr("Pause All") |
172 | text: root.installAll ? secondaryText : primaryText |
173 | anchors { |
174 | @@ -217,11 +241,15 @@ |
175 | updateList.currentIndex = i; |
176 | var item = updateList.currentItem; |
177 | var modelItem = updateManager.model[i]; |
178 | - if (modelItem.updateState == !root.installAll) { |
179 | + if (modelItem.updateState != root.installAll && !modelItem.updateReady) { |
180 | item.actionButton.clicked(); |
181 | } |
182 | } |
183 | } |
184 | + opacity: root.updatesAvailable > 0 ? 1 : 0 |
185 | + |
186 | + Behavior on opacity { PropertyAnimation { duration: UbuntuAnimation.SlowDuration |
187 | + easing: UbuntuAnimation.StandardEasing } } |
188 | } |
189 | |
190 | ListView { |
191 | @@ -290,16 +318,27 @@ |
192 | updateManager.applySystemUpdate(); |
193 | installingImageUpdate.visible = true; |
194 | } else if (modelData.updateState) { |
195 | - updateManager.pauseDownload(modelData.packageName); |
196 | + if (modelData.systemUpdate) { |
197 | + updateManager.pauseDownload(modelData.packageName); |
198 | + } else { |
199 | + modelData.updateState = false; |
200 | + tracker.pause(); |
201 | + } |
202 | } else { |
203 | - modelData.selected = true; |
204 | - updateManager.startDownload(modelData.packageName); |
205 | + if (!modelData.selected || modelData.systemUpdate) { |
206 | + modelData.selected = true; |
207 | + updateManager.startDownload(modelData.packageName); |
208 | + } else { |
209 | + modelData.updateState = true; |
210 | + tracker.resume(); |
211 | + } |
212 | } |
213 | } |
214 | } |
215 | |
216 | Label { |
217 | id: labelSize |
218 | + objectName: "labelSize" |
219 | text: convert_bytes_to_size(modelData.binaryFilesize) |
220 | anchors.bottom: labelVersion.bottom |
221 | anchors.right: parent.right |
222 | @@ -309,20 +348,23 @@ |
223 | |
224 | Label { |
225 | id: labelTitle |
226 | + objectName: "labelTitle" |
227 | anchors { |
228 | top: parent.top |
229 | left: parent.left |
230 | - right: buttonAppUpdate.right |
231 | + right: buttonAppUpdate.left |
232 | topMargin: units.gu(1) |
233 | + rightMargin: units.gu(1) |
234 | } |
235 | height: units.gu(3) |
236 | text: modelData.title |
237 | font.bold: true |
238 | - elide: Text.ElideRight |
239 | + elide: buttonAppUpdate.visible ? Text.ElideRight : Text.ElideNone |
240 | } |
241 | |
242 | Label { |
243 | id: labelUpdateStatus |
244 | + objectName: "labelUpdateStatus" |
245 | text: i18n.tr("Installing") |
246 | anchors.top: labelTitle.bottom |
247 | anchors.left: parent.left |
248 | @@ -342,20 +384,41 @@ |
249 | anchors.topMargin: units.gu(1) |
250 | anchors.right: parent.right |
251 | opacity: modelData.selected ? 1 : 0 |
252 | - value: modelData.downloadProgress |
253 | + value: modelData.systemUpdate ? modelData.downloadProgress : tracker.progress |
254 | minimumValue: 0 |
255 | maximumValue: 100 |
256 | |
257 | + DownloadTracker { |
258 | + id: tracker |
259 | + objectName: "tracker" |
260 | + packageName: modelData.packageName |
261 | + clickToken: modelData.clickToken |
262 | + download: modelData.downloadUrl |
263 | + |
264 | + onFinished: { |
265 | + progress.visible = false; |
266 | + buttonAppUpdate.visible = false; |
267 | + textArea.message = i18n.tr("Installed"); |
268 | + root.updatesAvailable -= 1; |
269 | + } |
270 | + |
271 | + onErrorFound: { |
272 | + modelData.updateState = false; |
273 | + textArea.message = error; |
274 | + } |
275 | + } |
276 | + |
277 | Behavior on opacity { PropertyAnimation { duration: UbuntuAnimation.SleepyDuration } } |
278 | } |
279 | |
280 | Label { |
281 | id: labelVersion |
282 | + objectName: "labelVersion" |
283 | anchors { |
284 | left: parent.left |
285 | right: buttonAppUpdate.right |
286 | - top: progress.bottom |
287 | - topMargin: units.gu(1) |
288 | + top: (!progress.visible || progress.opacity == 0) ? labelTitle.bottom : progress.bottom |
289 | + topMargin: (!progress.visible || progress.opacity == 0) ? 0 : units.gu(1) |
290 | bottom: parent.bottom |
291 | bottomMargin: units.gu(1) |
292 | } |
293 | @@ -369,12 +432,14 @@ |
294 | |
295 | ListItem.Standard { |
296 | id: notification |
297 | + objectName: "notification" |
298 | visible: false |
299 | anchors.bottom: configuration.top |
300 | } |
301 | |
302 | ListItem.SingleValue { |
303 | id: configuration |
304 | + objectName: "configuration" |
305 | anchors.bottom: parent.bottom |
306 | text: i18n.tr("Auto download") |
307 | value: { |
308 | @@ -390,7 +455,8 @@ |
309 | } |
310 | |
311 | Rectangle { |
312 | - id: updatedNotification |
313 | + id: updateNotification |
314 | + objectName: "updateNotification" |
315 | anchors { |
316 | left: parent.left |
317 | right: parent.right |
318 | @@ -408,7 +474,7 @@ |
319 | anchors.centerIn: parent |
320 | |
321 | Label { |
322 | - text: updatedNotification.text |
323 | + text: updateNotification.text |
324 | anchors.horizontalCenter: parent.horizontalCenter |
325 | fontSize: "large" |
326 | } |
327 | @@ -417,6 +483,7 @@ |
328 | |
329 | Rectangle { |
330 | id: installingImageUpdate |
331 | + objectName: "installingImageUpdate" |
332 | anchors.fill: parent |
333 | visible: false |
334 | |
335 | @@ -454,7 +521,7 @@ |
336 | result = bytes + i18n.tr(" bytes"); |
337 | } else if (bytes < SIZE_IN_MIB) { |
338 | size = (bytes / SIZE_IN_KIB).toFixed(1); |
339 | - result = bytes + i18n.tr(" KiB"); |
340 | + result = size + i18n.tr(" KiB"); |
341 | } else if (bytes < SIZE_IN_GIB) { |
342 | size = (bytes / SIZE_IN_MIB).toFixed(1); |
343 | result = size + i18n.tr(" MiB"); |
344 | |
345 | === added file 'plugins/system-update/download_tracker.cpp' |
346 | --- plugins/system-update/download_tracker.cpp 1970-01-01 00:00:00 +0000 |
347 | +++ plugins/system-update/download_tracker.cpp 2014-03-27 13:16:48 +0000 |
348 | @@ -0,0 +1,137 @@ |
349 | +/* |
350 | + * Copyright (C) 2014 - Canonical Ltd. |
351 | + * |
352 | + * This program is free software: you can redistribute it and/or modify it |
353 | + * under the terms of the GNU Lesser General Public License, as |
354 | + * published by the Free Software Foundation; either version 2.1 or 3.0 |
355 | + * of the License. |
356 | + * |
357 | + * This program is distributed in the hope that it will be useful, but |
358 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
359 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
360 | + * PURPOSE. See the applicable version of the GNU Lesser General Public |
361 | + * License for more details. |
362 | + * |
363 | + * You should have received a copy of both the GNU Lesser General Public |
364 | + * License along with this program. If not, see <http://www.gnu.org/licenses/> |
365 | + * |
366 | + * Authored by: Diego Sarmentero <diego.sarmentero@canonical.com> |
367 | + */ |
368 | + |
369 | +#include "download_tracker.h" |
370 | +#include "network/network.h" |
371 | +#include <ubuntu/download_manager/download_struct.h> |
372 | +#include <ubuntu/download_manager/error.h> |
373 | +#include <QProcessEnvironment> |
374 | + |
375 | +#define DOWNLOAD_COMMAND "post-download-command" |
376 | +#define APP_ID "app_id" |
377 | +#define PKCON_COMMAND "pkcon" |
378 | + |
379 | +namespace UpdatePlugin { |
380 | + |
381 | +DownloadTracker::DownloadTracker(QObject *parent) : |
382 | + QObject(parent), |
383 | + m_clickToken(""), |
384 | + m_downloadUrl(""), |
385 | + m_download(nullptr), |
386 | + m_manager(nullptr), |
387 | + m_progress(0) |
388 | +{ |
389 | +} |
390 | + |
391 | +void DownloadTracker::setDownload(const QString& url) |
392 | +{ |
393 | + if (url != "") { |
394 | + m_downloadUrl = url; |
395 | + startService(); |
396 | + } |
397 | +} |
398 | + |
399 | +void DownloadTracker::setClickToken(const QString& token) |
400 | +{ |
401 | + if (token != "") { |
402 | + m_clickToken = token; |
403 | + startService(); |
404 | + } |
405 | +} |
406 | + |
407 | +void DownloadTracker::setPackageName(const QString& package) |
408 | +{ |
409 | + if (package != "") { |
410 | + m_packageName = package; |
411 | + startService(); |
412 | + } |
413 | +} |
414 | + |
415 | +void DownloadTracker::startService() |
416 | +{ |
417 | + if (!m_clickToken.isEmpty() && !m_downloadUrl.isEmpty() && !m_packageName.isEmpty()) { |
418 | + if (m_manager == nullptr) { |
419 | + m_manager = Manager::createSessionManager("", this); |
420 | + |
421 | + QObject::connect(m_manager, SIGNAL(downloadCreated(Download*)), |
422 | + this, SLOT(bindDownload(Download*))); |
423 | + } |
424 | + QVariantMap vmap; |
425 | + QStringList args; |
426 | + QString command = getPkconCommand(); |
427 | + args << command << "-p" << "install-local" << "$file"; |
428 | + vmap[DOWNLOAD_COMMAND] = args; |
429 | + vmap[APP_ID] = m_packageName; |
430 | + StringMap map; |
431 | + map[X_CLICK_TOKEN] = m_clickToken; |
432 | + DownloadStruct dstruct = DownloadStruct(m_downloadUrl, vmap, map); |
433 | + m_manager->createDownload(dstruct); |
434 | + } |
435 | +} |
436 | + |
437 | +void DownloadTracker::bindDownload(Download* download) |
438 | +{ |
439 | + m_download = download; |
440 | + connect(m_download, SIGNAL(finished(const QString &)), this, |
441 | + SIGNAL(finished(const QString &))); |
442 | + connect(m_download, SIGNAL(error(Error*)), this, |
443 | + SLOT(registerError(Error*))); |
444 | + connect(m_download, SIGNAL(progress(qulonglong, qulonglong)), this, |
445 | + SLOT(setProgress(qulonglong, qulonglong))); |
446 | + |
447 | + m_download->start(); |
448 | +} |
449 | + |
450 | +void DownloadTracker::registerError(Error* error) |
451 | +{ |
452 | + Q_EMIT errorFound(error->errorString()); |
453 | +} |
454 | + |
455 | +void DownloadTracker::pause() |
456 | +{ |
457 | + if (m_download != nullptr) { |
458 | + m_download->pause(); |
459 | + } |
460 | +} |
461 | + |
462 | +void DownloadTracker::resume() |
463 | +{ |
464 | + if (m_download != nullptr) { |
465 | + m_download->resume(); |
466 | + } |
467 | +} |
468 | + |
469 | +QString DownloadTracker::getPkconCommand() |
470 | +{ |
471 | + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); |
472 | + QString command = environment.value("PKCON_COMMAND", QString(PKCON_COMMAND)); |
473 | + return command; |
474 | +} |
475 | + |
476 | +void DownloadTracker::setProgress(qulonglong received, qulonglong total) |
477 | +{ |
478 | + if (total > 0) { |
479 | + qulonglong result = (received * 100); |
480 | + m_progress = static_cast<int>(result / total); |
481 | + emit progressChanged(); |
482 | + } |
483 | +} |
484 | + |
485 | +} |
486 | |
487 | === added file 'plugins/system-update/download_tracker.h' |
488 | --- plugins/system-update/download_tracker.h 1970-01-01 00:00:00 +0000 |
489 | +++ plugins/system-update/download_tracker.h 2014-03-27 13:16:48 +0000 |
490 | @@ -0,0 +1,87 @@ |
491 | +/* |
492 | + * Copyright (C) 2014 - Canonical Ltd. |
493 | + * |
494 | + * This program is free software: you can redistribute it and/or modify it |
495 | + * under the terms of the GNU Lesser General Public License, as |
496 | + * published by the Free Software Foundation; either version 2.1 or 3.0 |
497 | + * of the License. |
498 | + * |
499 | + * This program is distributed in the hope that it will be useful, but |
500 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
501 | + * MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR |
502 | + * PURPOSE. See the applicable version of the GNU Lesser General Public |
503 | + * License for more details. |
504 | + * |
505 | + * You should have received a copy of both the GNU Lesser General Public |
506 | + * License along with this program. If not, see <http://www.gnu.org/licenses/> |
507 | + * |
508 | + * Authored by: Diego Sarmentero <diego.sarmentero@canonical.com> |
509 | + */ |
510 | + |
511 | + |
512 | +#ifndef DOWNLOADTRACKER_H |
513 | +#define DOWNLOADTRACKER_H |
514 | + |
515 | +#include <QObject> |
516 | +#include <QtQml> |
517 | +#include <QList> |
518 | +#include <QString> |
519 | +#include <ubuntu/download_manager/download.h> |
520 | +#include <ubuntu/download_manager/manager.h> |
521 | + |
522 | +using Ubuntu::DownloadManager::Download; |
523 | +using Ubuntu::DownloadManager::Manager; |
524 | + |
525 | +namespace Ubuntu { namespace DownloadManager { class Error; } } |
526 | + |
527 | +namespace UpdatePlugin { |
528 | + |
529 | +class DownloadTracker : public QObject |
530 | +{ |
531 | + Q_OBJECT |
532 | + Q_PROPERTY(QString clickToken READ clickToken WRITE setClickToken) |
533 | + Q_PROPERTY(QString download READ download WRITE setDownload) |
534 | + Q_PROPERTY(QString packageName READ packageName WRITE setPackageName) |
535 | + Q_PROPERTY(int progress READ progress NOTIFY progressChanged) |
536 | + |
537 | +public: |
538 | + explicit DownloadTracker(QObject *parent = 0); |
539 | + ~DownloadTracker() {} |
540 | + |
541 | + Q_INVOKABLE void pause(); |
542 | + Q_INVOKABLE void resume(); |
543 | + |
544 | + QString download() { return m_downloadUrl; } |
545 | + QString clickToken() { return m_clickToken; } |
546 | + QString packageName() { return m_packageName; } |
547 | + void setDownload(const QString& url); |
548 | + void setClickToken(const QString& token); |
549 | + void setPackageName(const QString& package); |
550 | + int progress() { return m_progress; } |
551 | + |
552 | +public Q_SLOTS: |
553 | + void bindDownload(Download* download); |
554 | + void setProgress(qulonglong received, qulonglong total); |
555 | + void registerError(Ubuntu::DownloadManager::Error* error); |
556 | + |
557 | +Q_SIGNALS: |
558 | + void error(const QString &errorMessage); |
559 | + void finished(const QString &path); |
560 | + void progressChanged(); |
561 | + void errorFound(const QString &error); |
562 | + |
563 | +private: |
564 | + QString m_clickToken; |
565 | + QString m_downloadUrl; |
566 | + QString m_packageName; |
567 | + Download* m_download; |
568 | + Manager* m_manager; |
569 | + int m_progress; |
570 | + |
571 | + void startService(); |
572 | + QString getPkconCommand(); |
573 | +}; |
574 | + |
575 | +} |
576 | + |
577 | +#endif // DOWNLOADTRACKER_H |
578 | |
579 | === added directory 'plugins/system-update/network' |
580 | === added file 'plugins/system-update/network/network.cpp' |
581 | --- plugins/system-update/network/network.cpp 1970-01-01 00:00:00 +0000 |
582 | +++ plugins/system-update/network/network.cpp 2014-03-27 13:16:48 +0000 |
583 | @@ -0,0 +1,165 @@ |
584 | +/* |
585 | + * Copyright 2013 Canonical Ltd. |
586 | + * |
587 | + * This library is free software; you can redistribute it and/or |
588 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
589 | + * License as published by the Free Software Foundation. |
590 | + * |
591 | + * This program is distributed in the hope that it will be useful, |
592 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
593 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
594 | + * General Public License for more details. |
595 | + * |
596 | + * You should have received a copy of the GNU Lesser General Public |
597 | + * License along with this library; if not, write to the |
598 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
599 | + * Boston, MA 02110-1301, USA. |
600 | + */ |
601 | + |
602 | +#include "network.h" |
603 | +#include <QJsonDocument> |
604 | +#include <QJsonObject> |
605 | +#include <QJsonArray> |
606 | +#include <QJsonValue> |
607 | +#include <QByteArray> |
608 | +#include <QUrl> |
609 | +#include <QProcessEnvironment> |
610 | + |
611 | +#define URL_APPS "https://myapps.developer.ubuntu.com/dev/api/click-metadata/" |
612 | +#define URL_PACKAGE "https://search.apps.ubuntu.com/api/v1/package/" |
613 | + |
614 | +namespace UpdatePlugin { |
615 | + |
616 | +Network::Network(QObject *parent) : |
617 | + QObject(parent), |
618 | + m_nam(this) |
619 | +{ |
620 | + m_request.setHeader(QNetworkRequest::ContentTypeHeader, |
621 | + "application/json"); |
622 | + |
623 | + QObject::connect(&m_nam, SIGNAL(finished(QNetworkReply*)), |
624 | + this, SLOT(onReply(QNetworkReply*))); |
625 | +} |
626 | + |
627 | +void Network::checkForNewVersions(QHash<QString, Update*> &apps) |
628 | +{ |
629 | + m_apps = apps; |
630 | + |
631 | + QJsonObject serializer; |
632 | + QJsonArray array; |
633 | + foreach(QString id, m_apps.keys()) { |
634 | + array.append(QJsonValue(m_apps.value(id)->getPackageName())); |
635 | + } |
636 | + |
637 | + serializer.insert("name", array); |
638 | + QJsonDocument doc(serializer); |
639 | + |
640 | + QByteArray content = doc.toJson(); |
641 | + |
642 | + QString urlApps = getUrlApps(); |
643 | + m_request.setUrl(QUrl(urlApps)); |
644 | + m_nam.post(m_request, content); |
645 | +} |
646 | + |
647 | + |
648 | + |
649 | +QString Network::getUrlApps() |
650 | +{ |
651 | + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); |
652 | + QString command = environment.value("URL_APPS", QString(URL_APPS)); |
653 | + return command; |
654 | +} |
655 | + |
656 | +QString Network::getUrlPackage() |
657 | +{ |
658 | + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); |
659 | + QString command = environment.value("URL_PACKAGE", QString(URL_PACKAGE)); |
660 | + return command; |
661 | +} |
662 | + |
663 | +void Network::onReply(QNetworkReply *reply) |
664 | +{ |
665 | + QVariant statusAttr = reply->attribute( |
666 | + QNetworkRequest::HttpStatusCodeAttribute); |
667 | + if (!statusAttr.isValid()) { |
668 | + Q_EMIT errorOccurred(); |
669 | + return; |
670 | + } |
671 | + |
672 | + int httpStatus = statusAttr.toInt(); |
673 | + |
674 | + if (httpStatus == 200 || httpStatus == 201) { |
675 | + if (reply->hasRawHeader(X_CLICK_TOKEN)) { |
676 | + Update* app = qobject_cast<Update*>( |
677 | + reply->request().originatingObject()); |
678 | + if (app != NULL) { |
679 | + QString header(reply->rawHeader(X_CLICK_TOKEN)); |
680 | + Q_EMIT clickTokenObtained(app, header); |
681 | + } |
682 | + reply->deleteLater(); |
683 | + return; |
684 | + } |
685 | + |
686 | + QByteArray payload = reply->readAll(); |
687 | + QJsonDocument document = QJsonDocument::fromJson(payload); |
688 | + |
689 | + if (document.isArray()) { |
690 | + QJsonArray array = document.array(); |
691 | + int i; |
692 | + bool updates = false; |
693 | + for (i = 0; i < array.size(); i++) { |
694 | + QJsonObject object = array.at(i).toObject(); |
695 | + QString name = object.value("name").toString(); |
696 | + QString version = object.value("version").toString(); |
697 | + QString icon_url = object.value("icon_url").toString(); |
698 | + int size = object.value("binary_filesize").toVariant().toInt(); |
699 | + if (m_apps.contains(name)) { |
700 | + m_apps[name]->setRemoteVersion(version); |
701 | + if (m_apps[name]->updateRequired()) { |
702 | + m_apps[name]->setIconUrl(icon_url); |
703 | + m_apps[name]->setBinaryFilesize(size); |
704 | + updates = true; |
705 | + } |
706 | + } |
707 | + } |
708 | + if (updates) { |
709 | + Q_EMIT updatesFound(); |
710 | + } else { |
711 | + Q_EMIT updatesNotFound(); |
712 | + } |
713 | + } else if (document.isObject()) { |
714 | + QJsonObject object = document.object(); |
715 | + QString url = object.value("download_url").toString(); |
716 | + QString name = object.value("name").toString(); |
717 | + Q_EMIT downloadUrlFound(name, url); |
718 | + } else { |
719 | + Q_EMIT errorOccurred(); |
720 | + } |
721 | + } else { |
722 | + Q_EMIT errorOccurred(); |
723 | + } |
724 | + |
725 | + reply->deleteLater(); |
726 | +} |
727 | + |
728 | +void Network::getResourceUrl(const QString &packagename) |
729 | +{ |
730 | + QString urlPackage = getUrlPackage(); |
731 | + m_request.setUrl(QUrl(urlPackage + packagename)); |
732 | + m_nam.get(m_request); |
733 | +} |
734 | + |
735 | +void Network::getClickToken(Update *app, const QString &url, |
736 | + const QString &authHeader) |
737 | +{ |
738 | + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); |
739 | + QString signUrl = environment.value("CLICK_TOKEN_URL", url); |
740 | + QUrl query(signUrl); |
741 | + query.setQuery(authHeader); |
742 | + QNetworkRequest request; |
743 | + request.setUrl(query); |
744 | + request.setOriginatingObject(app); |
745 | + m_nam.head(request); |
746 | +} |
747 | + |
748 | +} |
749 | |
750 | === added file 'plugins/system-update/network/network.h' |
751 | --- plugins/system-update/network/network.h 1970-01-01 00:00:00 +0000 |
752 | +++ plugins/system-update/network/network.h 2014-03-27 13:16:48 +0000 |
753 | @@ -0,0 +1,64 @@ |
754 | +/* |
755 | + * Copyright 2013 Canonical Ltd. |
756 | + * |
757 | + * This library is free software; you can redistribute it and/or |
758 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
759 | + * License as published by the Free Software Foundation. |
760 | + * |
761 | + * This program is distributed in the hope that it will be useful, |
762 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
763 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
764 | + * General Public License for more details. |
765 | + * |
766 | + * You should have received a copy of the GNU Lesser General Public |
767 | + * License along with this library; if not, write to the |
768 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
769 | + * Boston, MA 02110-1301, USA. |
770 | + */ |
771 | + |
772 | +#ifndef NETWORK_H |
773 | +#define NETWORK_H |
774 | + |
775 | +#include <QObject> |
776 | +#include <QtNetwork/QNetworkAccessManager> |
777 | +#include <QtNetwork/QNetworkReply> |
778 | +#include <QHash> |
779 | +#include "../update.h" |
780 | + |
781 | +#define X_CLICK_TOKEN "X-Click-Token" |
782 | + |
783 | +namespace UpdatePlugin { |
784 | + |
785 | +class Network : public QObject |
786 | +{ |
787 | + Q_OBJECT |
788 | +public: |
789 | + explicit Network(QObject *parent = 0); |
790 | + |
791 | + void checkForNewVersions(QHash<QString, Update*> &apps); |
792 | + void getResourceUrl(const QString &packagename); |
793 | + void getClickToken(Update *app, const QString &url, |
794 | + const QString &authHeader); |
795 | + |
796 | +Q_SIGNALS: |
797 | + void updatesFound(); |
798 | + void updatesNotFound(); |
799 | + void errorOccurred(); |
800 | + void downloadUrlFound(const QString &packagename, const QString &url); |
801 | + void clickTokenObtained(Update *app, const QString &clickToken); |
802 | + |
803 | +private Q_SLOTS: |
804 | + void onReply(QNetworkReply*); |
805 | + |
806 | +private: |
807 | + QNetworkAccessManager m_nam; |
808 | + QNetworkRequest m_request; |
809 | + QHash<QString, Update*> m_apps; |
810 | + |
811 | + QString getUrlApps(); |
812 | + QString getUrlPackage(); |
813 | +}; |
814 | + |
815 | +} |
816 | + |
817 | +#endif // NETWORK_H |
818 | |
819 | === modified file 'plugins/system-update/plugin.cpp' |
820 | --- plugins/system-update/plugin.cpp 2014-01-23 19:29:34 +0000 |
821 | +++ plugins/system-update/plugin.cpp 2014-03-27 13:16:48 +0000 |
822 | @@ -24,6 +24,7 @@ |
823 | #include "update_manager.h" |
824 | #include "system_update.h" |
825 | #include "update.h" |
826 | +#include "download_tracker.h" |
827 | |
828 | using namespace UpdatePlugin; |
829 | |
830 | @@ -35,6 +36,7 @@ |
831 | qmlRegisterType<UpdateManager>(uri, 1, 0, "UpdateManager"); |
832 | qmlRegisterType<SystemUpdate>(uri, 1, 0, "SystemUpdate"); |
833 | qmlRegisterType<Update>(uri, 1, 0, "Update"); |
834 | + qmlRegisterType<DownloadTracker>(uri, 1, 0, "DownloadTracker"); |
835 | } |
836 | |
837 | void BackendPlugin::initializeEngine(QQmlEngine *engine, const char *uri) |
838 | |
839 | === modified file 'plugins/system-update/system_update.cpp' |
840 | --- plugins/system-update/system_update.cpp 2014-01-27 18:43:14 +0000 |
841 | +++ plugins/system-update/system_update.cpp 2014-03-27 13:16:48 +0000 |
842 | @@ -165,7 +165,11 @@ |
843 | update->setLastUpdateDate(lastUpdateDate); |
844 | update->setIconUrl(QString("file:///usr/share/ubuntu/settings/system/icons/distributor-logo.png")); |
845 | |
846 | - Q_EMIT this->updateAvailable(packageName, update); |
847 | + if (update->updateRequired()) { |
848 | + Q_EMIT updateAvailable(packageName, update); |
849 | + } else { |
850 | + Q_EMIT updateNotFound(); |
851 | + } |
852 | } |
853 | |
854 | void SystemUpdate::updateDownloadProgress(int percentage, double eta) |
855 | |
856 | === modified file 'plugins/system-update/system_update.h' |
857 | --- plugins/system-update/system_update.h 2014-01-27 10:14:51 +0000 |
858 | +++ plugins/system-update/system_update.h 2014-03-27 13:16:48 +0000 |
859 | @@ -56,6 +56,7 @@ |
860 | |
861 | Q_SIGNALS: |
862 | void updateAvailable(const QString& packageName, Update *update); |
863 | + void updateNotFound(); |
864 | void updateProgress(int percentage, double eta); |
865 | void updatePaused(int percentage); |
866 | void updateDownloaded(); |
867 | |
868 | === modified file 'plugins/system-update/update.cpp' |
869 | --- plugins/system-update/update.cpp 2014-01-27 18:43:14 +0000 |
870 | +++ plugins/system-update/update.cpp 2014-03-27 13:16:48 +0000 |
871 | @@ -21,12 +21,15 @@ |
872 | #include "update.h" |
873 | #include <QStringList> |
874 | #include <apt-pkg/debversion.h> |
875 | +#include <QProcessEnvironment> |
876 | |
877 | namespace UpdatePlugin { |
878 | |
879 | Update::Update(QObject *parent) : |
880 | QObject(parent), |
881 | m_binary_filesize(0), |
882 | + m_click_url(""), |
883 | + m_downloadUrl(""), |
884 | m_download_progress(0), |
885 | m_error(""), |
886 | m_icon_url(""), |
887 | @@ -58,11 +61,14 @@ |
888 | void Update::setRemoteVersion(QString& version) |
889 | { |
890 | m_remote_version = version; |
891 | - |
892 | - int result = debVS.CmpVersion(m_local_version.toUtf8().data(), |
893 | - m_remote_version.toUtf8().data()); |
894 | - |
895 | - m_update = result < 0; |
896 | + if (getIgnoreUpdates()) { |
897 | + int result = debVS.CmpVersion(m_local_version.toUtf8().data(), |
898 | + m_remote_version.toUtf8().data()); |
899 | + |
900 | + m_update = result < 0; |
901 | + } else { |
902 | + m_update = false; |
903 | + } |
904 | } |
905 | |
906 | void Update::setError(QString error) |
907 | @@ -120,4 +126,16 @@ |
908 | Q_EMIT downloadProgressChanged(); |
909 | } |
910 | |
911 | +void Update::setDownloadUrl(const QString &url) { |
912 | + m_downloadUrl = url; |
913 | + Q_EMIT downloadUrlChanged(); |
914 | +} |
915 | + |
916 | +bool Update::getIgnoreUpdates() |
917 | +{ |
918 | + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); |
919 | + QString value = environment.value("IGNORE_UPDATES", QString("NOT_IGNORE_UPDATES")); |
920 | + return value == "IGNORE_UPDATES"; |
921 | +} |
922 | + |
923 | } |
924 | |
925 | === modified file 'plugins/system-update/update.h' |
926 | --- plugins/system-update/update.h 2014-01-27 10:14:51 +0000 |
927 | +++ plugins/system-update/update.h 2014-03-27 13:16:48 +0000 |
928 | @@ -54,6 +54,8 @@ |
929 | NOTIFY lastUpdateDateChanged) |
930 | Q_PROPERTY(int downloadProgress READ downloadProgress |
931 | NOTIFY downloadProgressChanged) |
932 | + Q_PROPERTY(QString downloadUrl READ downloadUrl NOTIFY downloadUrlChanged) |
933 | + Q_PROPERTY(QString clickToken READ clickToken NOTIFY clickTokenChanged) |
934 | |
935 | Q_SIGNALS: |
936 | void systemUpdateChanged(); |
937 | @@ -68,6 +70,8 @@ |
938 | void errorChanged(); |
939 | void downloadProgressChanged(); |
940 | void lastUpdateDateChanged(); |
941 | + void downloadUrlChanged(); |
942 | + void clickTokenChanged(); |
943 | |
944 | public: |
945 | explicit Update(QObject *parent = 0); |
946 | @@ -87,6 +91,9 @@ |
947 | bool updateReady() { return m_update_ready; } |
948 | bool selected() { return m_selected; } |
949 | QString getError() { return m_error; } |
950 | + const QString& getClickUrl() const { return m_click_url; } |
951 | + QString downloadUrl() { return m_downloadUrl; } |
952 | + QString clickToken() { return m_clickToken; } |
953 | |
954 | void setSystemUpdate(bool isSystem); |
955 | void initializeApplication(QString packagename, QString title, |
956 | @@ -101,9 +108,15 @@ |
957 | void setError(QString error); |
958 | void setUpdateAvailable(bool available) { m_update = available; } |
959 | void setLastUpdateDate(const QString date); |
960 | + void setClickUrl(const QString &url) { m_click_url = url; } |
961 | + void setDownloadUrl(const QString &url); |
962 | + void setClickToken(const QString &token) { m_clickToken = token; Q_EMIT clickTokenChanged(); } |
963 | |
964 | private: |
965 | int m_binary_filesize; |
966 | + QString m_click_url; |
967 | + QString m_clickToken; |
968 | + QString m_downloadUrl; |
969 | int m_download_progress; |
970 | QString m_error; |
971 | QString m_icon_url; |
972 | @@ -117,6 +130,8 @@ |
973 | bool m_update; |
974 | bool m_update_ready; |
975 | bool m_update_state; |
976 | + |
977 | + bool getIgnoreUpdates(); |
978 | }; |
979 | |
980 | } |
981 | |
982 | === modified file 'plugins/system-update/update_manager.cpp' |
983 | --- plugins/system-update/update_manager.cpp 2014-02-26 11:39:47 +0000 |
984 | +++ plugins/system-update/update_manager.cpp 2014-03-27 13:16:48 +0000 |
985 | @@ -25,15 +25,46 @@ |
986 | #include <QJsonObject> |
987 | #include <QJsonArray> |
988 | #include <QJsonValue> |
989 | +#include <QProcessEnvironment> |
990 | + |
991 | +#define CLICK_COMMAND "click" |
992 | |
993 | namespace UpdatePlugin { |
994 | |
995 | UpdateManager::UpdateManager(QObject *parent): |
996 | - QObject(parent) |
997 | + QObject(parent), |
998 | + m_systemCheckingUpdate(false), |
999 | + m_clickCheckingUpdate(false), |
1000 | + m_checkingUpdates(0) |
1001 | { |
1002 | + // SSO SERVICE |
1003 | + QObject::connect(&m_service, SIGNAL(credentialsFound(const Token&)), |
1004 | + this, SLOT(handleCredentialsFound(Token))); |
1005 | + QObject::connect(&m_service, SIGNAL(credentialsNotFound()), |
1006 | + this, SIGNAL(credentialsNotFound())); |
1007 | + QObject::connect(&m_service, SIGNAL(credentialsNotFound()), |
1008 | + this, SLOT(clickUpdateNotAvailable())); |
1009 | + // PROCESS |
1010 | + QObject::connect(&m_process, SIGNAL(finished(int)), |
1011 | + this, SLOT(processOutput())); |
1012 | + // NETWORK |
1013 | + QObject::connect(&m_network, SIGNAL(updatesFound()), |
1014 | + this, SLOT(processUpdates())); |
1015 | + QObject::connect(&m_network, SIGNAL(updatesNotFound()), |
1016 | + this, SLOT(clickUpdateNotAvailable())); |
1017 | + QObject::connect(&m_network, SIGNAL(errorOccurred()), |
1018 | + this, SIGNAL(errorFound())); |
1019 | + QObject::connect(&m_network, |
1020 | + SIGNAL(clickTokenObtained(Update*, const QString&)), |
1021 | + this, SLOT(clickTokenReceived(Update*, const QString&))); |
1022 | + QObject::connect(&m_network, |
1023 | + SIGNAL(downloadUrlFound(const QString&, const QString&)), |
1024 | + this, SLOT(downloadUrlObtained(const QString&, const QString&))); |
1025 | // SYSTEM UPDATE |
1026 | QObject::connect(&m_systemUpdate, SIGNAL(updateAvailable(const QString&, Update*)), |
1027 | this, SLOT(registerSystemUpdate(const QString&, Update*))); |
1028 | + QObject::connect(&m_systemUpdate, SIGNAL(updateNotFound()), |
1029 | + this, SLOT(systemUpdateNotAvailable())); |
1030 | QObject::connect(&m_systemUpdate, SIGNAL(downloadModeChanged()), |
1031 | SIGNAL(downloadModeChanged())); |
1032 | QObject::connect(&m_systemUpdate, SIGNAL(updateDownloaded()), |
1033 | @@ -50,26 +81,127 @@ |
1034 | { |
1035 | } |
1036 | |
1037 | +void UpdateManager::clickUpdateNotAvailable() |
1038 | +{ |
1039 | + m_clickCheckingUpdate = false; |
1040 | + reportCheckState(); |
1041 | + updateNotAvailable(); |
1042 | +} |
1043 | + |
1044 | +void UpdateManager::systemUpdateNotAvailable() |
1045 | +{ |
1046 | + m_systemCheckingUpdate = false; |
1047 | + reportCheckState(); |
1048 | + updateNotAvailable(); |
1049 | +} |
1050 | + |
1051 | +void UpdateManager::updateNotAvailable() |
1052 | +{ |
1053 | + m_checkingUpdates--; |
1054 | + if (m_checkingUpdates == 0 && m_model.count() == 0) { |
1055 | + Q_EMIT updatesNotFound(); |
1056 | + } |
1057 | +} |
1058 | + |
1059 | +void UpdateManager::reportCheckState() |
1060 | +{ |
1061 | + if (!m_clickCheckingUpdate && !m_systemCheckingUpdate) { |
1062 | + Q_EMIT checkFinished(); |
1063 | + } |
1064 | +} |
1065 | + |
1066 | void UpdateManager::checkUpdates() |
1067 | { |
1068 | + m_systemCheckingUpdate = true; |
1069 | + m_clickCheckingUpdate = true; |
1070 | + m_checkingUpdates = 2; |
1071 | m_model.clear(); |
1072 | m_apps.clear(); |
1073 | Q_EMIT modelChanged(); |
1074 | - m_systemUpdate.checkForUpdate(); |
1075 | + if (getCheckForCredentials()) { |
1076 | + m_systemUpdate.checkForUpdate(); |
1077 | + m_service.getCredentials(); |
1078 | + } else { |
1079 | + systemUpdateNotAvailable(); |
1080 | + Token token("", "", "", ""); |
1081 | + handleCredentialsFound(token); |
1082 | + } |
1083 | +} |
1084 | + |
1085 | +void UpdateManager::handleCredentialsFound(Token token) |
1086 | +{ |
1087 | + m_token = token; |
1088 | + QStringList args("list"); |
1089 | + args << "--manifest"; |
1090 | + QString command = getClickCommand(); |
1091 | + m_process.start(command, args); |
1092 | +} |
1093 | + |
1094 | +QString UpdateManager::getClickCommand() |
1095 | +{ |
1096 | + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); |
1097 | + QString command = environment.value("CLICK_COMMAND", QString(CLICK_COMMAND)); |
1098 | + return command; |
1099 | +} |
1100 | + |
1101 | +bool UpdateManager::getCheckForCredentials() |
1102 | +{ |
1103 | + QProcessEnvironment environment = QProcessEnvironment::systemEnvironment(); |
1104 | + QString value = environment.value("IGNORE_CREDENTIALS", QString("CHECK_CREDENTIALS")); |
1105 | + return value == "CHECK_CREDENTIALS"; |
1106 | +} |
1107 | + |
1108 | +void UpdateManager::processOutput() |
1109 | +{ |
1110 | + QString output(m_process.readAllStandardOutput()); |
1111 | + |
1112 | + QJsonDocument document = QJsonDocument::fromJson(output.toUtf8()); |
1113 | + |
1114 | + QJsonArray array = document.array(); |
1115 | + |
1116 | + int i; |
1117 | + for (i = 0; i < array.size(); i++) { |
1118 | + QJsonObject object = array.at(i).toObject(); |
1119 | + QString name = object.value("name").toString(); |
1120 | + QString title = object.value("title").toString(); |
1121 | + QString version = object.value("version").toString(); |
1122 | + Update *app = new Update(); |
1123 | + app->initializeApplication(name, title, version); |
1124 | + m_apps[app->getPackageName()] = app; |
1125 | + } |
1126 | + |
1127 | + m_network.checkForNewVersions(m_apps); |
1128 | +} |
1129 | + |
1130 | +void UpdateManager::processUpdates() |
1131 | +{ |
1132 | + m_clickCheckingUpdate = false; |
1133 | + bool updateAvailable = false; |
1134 | + foreach (QString id, m_apps.keys()) { |
1135 | + Update *app = m_apps.value(id); |
1136 | + if(app->updateRequired()) { |
1137 | + updateAvailable = true; |
1138 | + m_model.append(QVariant::fromValue(app)); |
1139 | + } |
1140 | + } |
1141 | + |
1142 | + if (updateAvailable) { |
1143 | + Q_EMIT modelChanged(); |
1144 | + Q_EMIT updateAvailableFound(false); |
1145 | + } |
1146 | + reportCheckState(); |
1147 | } |
1148 | |
1149 | void UpdateManager::registerSystemUpdate(const QString& packageName, Update *update) |
1150 | { |
1151 | - if (update->updateRequired()) { |
1152 | - if (!m_apps.contains(packageName)) { |
1153 | - m_apps[packageName] = update; |
1154 | - m_model.insert(0, QVariant::fromValue(update)); |
1155 | - Q_EMIT modelChanged(); |
1156 | - } |
1157 | - Q_EMIT updateAvailableFound(update->updateState()); |
1158 | - } else { |
1159 | - Q_EMIT updatesNotFound(); |
1160 | + m_systemCheckingUpdate = false; |
1161 | + if (!m_apps.contains(packageName)) { |
1162 | + m_apps[packageName] = update; |
1163 | + m_model.insert(0, QVariant::fromValue(update)); |
1164 | + Q_EMIT modelChanged(); |
1165 | } |
1166 | + Q_EMIT updateAvailableFound(update->updateState()); |
1167 | + reportCheckState(); |
1168 | } |
1169 | |
1170 | void UpdateManager::systemUpdatePaused(int value) |
1171 | @@ -85,17 +217,25 @@ |
1172 | void UpdateManager::startDownload(const QString &packagename) |
1173 | { |
1174 | m_apps[packagename]->setUpdateState(true); |
1175 | - m_systemUpdate.downloadUpdate(); |
1176 | + if (m_apps[packagename]->systemUpdate()) { |
1177 | + m_systemUpdate.downloadUpdate(); |
1178 | + } else { |
1179 | + m_network.getResourceUrl(packagename); |
1180 | + } |
1181 | } |
1182 | |
1183 | void UpdateManager::retryDownload(const QString &packagename) |
1184 | { |
1185 | - Update *update = m_apps.take(packagename); |
1186 | - m_systemUpdate.cancelUpdate(); |
1187 | - m_model.removeAt(0); |
1188 | - update->deleteLater(); |
1189 | - Q_EMIT modelChanged(); |
1190 | - m_systemUpdate.checkForUpdate(); |
1191 | + if (m_apps[packagename]->systemUpdate()) { |
1192 | + Update *update = m_apps.take(packagename); |
1193 | + m_systemUpdate.cancelUpdate(); |
1194 | + m_model.removeAt(0); |
1195 | + update->deleteLater(); |
1196 | + Q_EMIT modelChanged(); |
1197 | + m_systemUpdate.checkForUpdate(); |
1198 | + } else { |
1199 | + startDownload(packagename); |
1200 | + } |
1201 | } |
1202 | |
1203 | void UpdateManager::pauseDownload(const QString &packagename) |
1204 | @@ -104,4 +244,25 @@ |
1205 | m_systemUpdate.pauseDownload(); |
1206 | } |
1207 | |
1208 | +void UpdateManager::downloadUrlObtained(const QString &packagename, |
1209 | + const QString &url) |
1210 | +{ |
1211 | + if (m_token.isValid()) { |
1212 | + QString authHeader = m_token.signUrl(url, QStringLiteral("HEAD"), true); |
1213 | + Update *app = m_apps[packagename]; |
1214 | + app->setClickUrl(url); |
1215 | + m_network.getClickToken(app, url, authHeader); |
1216 | + } else { |
1217 | + Update *app = m_apps[packagename]; |
1218 | + app->setError("Invalid User Token"); |
1219 | + } |
1220 | +} |
1221 | + |
1222 | +void UpdateManager::clickTokenReceived(Update *app, const QString &clickToken) |
1223 | +{ |
1224 | + app->setError(""); |
1225 | + app->setClickToken(clickToken); |
1226 | + app->setDownloadUrl(app->getClickUrl()); |
1227 | +} |
1228 | + |
1229 | } |
1230 | |
1231 | === modified file 'plugins/system-update/update_manager.h' |
1232 | --- plugins/system-update/update_manager.h 2014-02-26 11:39:47 +0000 |
1233 | +++ plugins/system-update/update_manager.h 2014-03-27 13:16:48 +0000 |
1234 | @@ -29,6 +29,21 @@ |
1235 | #include <QVariantList> |
1236 | #include "system_update.h" |
1237 | #include "update.h" |
1238 | +#include <token.h> |
1239 | + |
1240 | +#ifdef TESTS |
1241 | +#include "../../tests/plugins/system-update/fakeprocess.h" |
1242 | +#include "../../tests/plugins/system-update/fakenetwork.h" |
1243 | +#include "../../tests/plugins/system-update/fakessoservice.h" |
1244 | +#include "../../tests/plugins/system-update/fakesystemupdate.h" |
1245 | +#else |
1246 | +#include <ssoservice.h> |
1247 | +#include <QProcess> |
1248 | +#include "network/network.h" |
1249 | +#include "system_update.h" |
1250 | +#endif |
1251 | + |
1252 | +using namespace UbuntuOne; |
1253 | |
1254 | namespace UpdatePlugin { |
1255 | |
1256 | @@ -41,8 +56,10 @@ |
1257 | Q_PROPERTY(int currentBuildNumber READ currentBuildNumber) |
1258 | |
1259 | Q_SIGNALS: |
1260 | + void checkFinished(); |
1261 | void modelChanged(); |
1262 | void updatesNotFound(); |
1263 | + void credentialsNotFound(); |
1264 | void updateAvailableFound(bool downloading); |
1265 | void errorFound(); |
1266 | void downloadModeChanged(); |
1267 | @@ -70,21 +87,49 @@ |
1268 | QHash<QString, Update*> get_apps() { return m_apps; } |
1269 | QVariantList get_model() { return m_model; } |
1270 | int get_downloadMode() { return m_downloadMode; } |
1271 | + void set_token(Token& t) { m_token = t; } |
1272 | + Token get_token() { return m_token; } |
1273 | #endif |
1274 | |
1275 | public Q_SLOTS: |
1276 | void registerSystemUpdate(const QString& packageName, Update *update); |
1277 | |
1278 | private Q_SLOTS: |
1279 | + void clickUpdateNotAvailable(); |
1280 | + void systemUpdateNotAvailable(); |
1281 | void systemUpdatePaused(int value); |
1282 | + void processOutput(); |
1283 | + void processUpdates(); |
1284 | + void downloadUrlObtained(const QString &packagename, const QString &url); |
1285 | + void handleCredentialsFound(Token token); |
1286 | + void clickTokenReceived(Update *app, const QString &clickToken); |
1287 | |
1288 | private: |
1289 | + bool m_systemCheckingUpdate; |
1290 | + bool m_clickCheckingUpdate; |
1291 | + int m_checkingUpdates; |
1292 | QHash<QString, Update*> m_apps; |
1293 | int m_downloadMode; |
1294 | QVariantList m_model; |
1295 | + Token m_token; |
1296 | + |
1297 | +#ifdef TESTS |
1298 | + FakeNetwork m_network; |
1299 | + FakeProcess m_process; |
1300 | + FakeSsoService m_service; |
1301 | + FakeSystemUpdate m_systemUpdate; |
1302 | +#else |
1303 | + Network m_network; |
1304 | + QProcess m_process; |
1305 | + SSOService m_service; |
1306 | SystemUpdate m_systemUpdate; |
1307 | +#endif |
1308 | |
1309 | void checkForUpdates(); |
1310 | + QString getClickCommand(); |
1311 | + bool getCheckForCredentials(); |
1312 | + void reportCheckState(); |
1313 | + void updateNotAvailable(); |
1314 | }; |
1315 | |
1316 | } |
1317 | |
1318 | === modified file 'tests/autopilot/ubuntu_system_settings/tests/__init__.py' |
1319 | --- tests/autopilot/ubuntu_system_settings/tests/__init__.py 2014-03-10 11:24:08 +0000 |
1320 | +++ tests/autopilot/ubuntu_system_settings/tests/__init__.py 2014-03-27 13:16:48 +0000 |
1321 | @@ -241,11 +241,9 @@ |
1322 | button = self.main_view.select_single( |
1323 | objectName='entryComponent-system-update') |
1324 | self.assertThat(button, NotEquals(None)) |
1325 | - self.pointer.move_to_object(button) |
1326 | - self.pointer.click() |
1327 | + self.scroll_to_and_click(button) |
1328 | |
1329 | @property |
1330 | def updates_page(self): |
1331 | """ Return 'System Update' page """ |
1332 | - return self.main_view.select_single( |
1333 | - objectName='entryComponent-system-update') |
1334 | + return self.main_view.select_single(objectName='systemUpdatesPage') |
1335 | |
1336 | === modified file 'tests/autopilot/ubuntu_system_settings/tests/test_system_updates.py' |
1337 | --- tests/autopilot/ubuntu_system_settings/tests/test_system_updates.py 2014-02-24 16:24:39 +0000 |
1338 | +++ tests/autopilot/ubuntu_system_settings/tests/test_system_updates.py 2014-03-27 13:16:48 +0000 |
1339 | @@ -5,8 +5,13 @@ |
1340 | # under the terms of the GNU General Public License version 3, as published |
1341 | # by the Free Software Foundation. |
1342 | |
1343 | +from __future__ import absolute_import |
1344 | + |
1345 | +import os |
1346 | + |
1347 | from autopilot.introspection.dbus import StateNotFoundError |
1348 | -from testtools.matchers import NotEquals, raises |
1349 | +from autopilot.matchers import Eventually |
1350 | +from testtools.matchers import Equals, NotEquals, raises |
1351 | |
1352 | from ubuntu_system_settings.tests import SystemUpdatesBaseTestCase |
1353 | |
1354 | @@ -20,6 +25,8 @@ |
1355 | |
1356 | def setUp(self): |
1357 | # Set environment variables |
1358 | + os.environ["IGNORE_CREDENTIALS"] = "True" |
1359 | + os.environ["IGNORE_UPDATES"] = "True" |
1360 | super(SystemUpdatesTestCases, self).setUp() |
1361 | |
1362 | def test_show_updates(self): |
1363 | @@ -27,10 +34,72 @@ |
1364 | updates = self.updates_page |
1365 | self.assertThat(updates, NotEquals(None)) |
1366 | # Move to text field |
1367 | - self.pointer.move_to_object(updates) |
1368 | - self.pointer.click() |
1369 | + self.scroll_to_and_click(updates) |
1370 | |
1371 | def test_updates_not_in_main(self): |
1372 | """Check that the updates notification is shown in main.""" |
1373 | self.assertThat(lambda: self.main_view.select_single( |
1374 | objectName='entryComponent-updates'), raises(StateNotFoundError)) |
1375 | + |
1376 | + def test_configuration(self): |
1377 | + """Check the configuration button.""" |
1378 | + self.assertThat(lambda: self.main_view.select_single( |
1379 | + objectName='configurationPage'), raises(StateNotFoundError)) |
1380 | + updates = self.updates_page |
1381 | + self.assertThat(updates, NotEquals(None)) |
1382 | + configuration = updates.select_single(objectName='configuration') |
1383 | + self.assertThat(configuration, NotEquals(None)) |
1384 | + self.scroll_to_and_click(configuration) |
1385 | + |
1386 | + def test_check_for_updates_area(self): |
1387 | + """Check that the updates area is shown on opening.""" |
1388 | + updates = self.updates_page |
1389 | + self.assertThat(updates, NotEquals(None)) |
1390 | + checkForUpdatesArea = updates.select_single( |
1391 | + objectName='checkForUpdatesArea') |
1392 | + self.assertThat(checkForUpdatesArea, NotEquals(None)) |
1393 | + self.assertThat(checkForUpdatesArea.visible, Equals(True)) |
1394 | + self.assertThat(checkForUpdatesArea.visible, |
1395 | + Eventually(NotEquals(True))) |
1396 | + |
1397 | + def test_searching_state(self): |
1398 | + """Check how the ui reacts to searching state.""" |
1399 | + updates = self.updates_page |
1400 | + self.assertThat(updates, NotEquals(None)) |
1401 | + updates.state.wait_for("SEARCHING") |
1402 | + self.assertThat(updates.state, Equals("SEARCHING")) |
1403 | + notification = updates.select_single( |
1404 | + objectName='notification') |
1405 | + self.assertThat(notification, NotEquals(None)) |
1406 | + self.assertThat(notification.visible, Equals(False)) |
1407 | + installAllButton = updates.select_single( |
1408 | + objectName='installAllButton') |
1409 | + self.assertThat(installAllButton, NotEquals(None)) |
1410 | + self.assertThat(installAllButton.visible, Equals(False)) |
1411 | + updateNotification = updates.select_single( |
1412 | + objectName='updateNotification') |
1413 | + self.assertThat(updateNotification, NotEquals(None)) |
1414 | + self.assertThat(updateNotification.visible, Equals(False)) |
1415 | + checkForUpdatesArea = updates.select_single( |
1416 | + objectName='checkForUpdatesArea') |
1417 | + self.assertThat(checkForUpdatesArea, NotEquals(None)) |
1418 | + self.assertThat(checkForUpdatesArea.visible, Equals(True)) |
1419 | + |
1420 | + def test_no_updates_state(self): |
1421 | + """Check how the ui reacts to no updates state.""" |
1422 | + updates = self.updates_page |
1423 | + self.assertThat(updates, NotEquals(None)) |
1424 | + updates.state.wait_for("NOUPDATES") |
1425 | + self.assertThat(updates.state, Equals("NOUPDATES")) |
1426 | + updateList = updates.select_single( |
1427 | + objectName='updateList') |
1428 | + self.assertThat(updateList, NotEquals(None)) |
1429 | + self.assertThat(updateList.visible, Equals(False)) |
1430 | + installAllButton = updates.select_single( |
1431 | + objectName='installAllButton') |
1432 | + self.assertThat(installAllButton, NotEquals(None)) |
1433 | + self.assertThat(installAllButton.visible, Equals(False)) |
1434 | + updateNotification = updates.select_single( |
1435 | + objectName='updateNotification') |
1436 | + self.assertThat(updateNotification, NotEquals(None)) |
1437 | + self.assertThat(updateNotification.visible, Equals(True)) |
1438 | |
1439 | === modified file 'tests/plugins/system-update/CMakeLists.txt' |
1440 | --- tests/plugins/system-update/CMakeLists.txt 2014-02-03 11:10:35 +0000 |
1441 | +++ tests/plugins/system-update/CMakeLists.txt 2014-03-27 13:16:48 +0000 |
1442 | @@ -2,8 +2,20 @@ |
1443 | include_directories(${CMAKE_CURRENT_BINARY_DIR} ../../../plugins/system-update) |
1444 | add_definitions(-DTESTS) |
1445 | |
1446 | +# Need to get libsignon/accounts here, as they get exposed in headers |
1447 | +find_package (PkgConfig REQUIRED) |
1448 | +pkg_check_modules(UBUNTUONEAUTH REQUIRED ubuntuoneauth-2.0) |
1449 | +add_definitions(${UBUNTUONEAUTH_CFLAGS} ${UBUNTUONEAUTH_CFLAGS_OTHER}) |
1450 | + |
1451 | add_executable(tst-update-manager |
1452 | tst_updatemanager.cpp |
1453 | + fakeprocess.cpp |
1454 | + fakeprocess.h |
1455 | + fakenetwork.cpp |
1456 | + fakenetwork.h |
1457 | + fakessoservice.cpp |
1458 | + fakessoservice.h |
1459 | + fakesystemupdate.cpp |
1460 | ../../../plugins/system-update/update.cpp |
1461 | ../../../plugins/system-update/update_manager.cpp |
1462 | ../../../plugins/system-update/system_update.cpp |
1463 | @@ -17,10 +29,15 @@ |
1464 | # set the path to the library folder |
1465 | include_directories(/usr/include/apt-pkg/) |
1466 | |
1467 | -target_link_libraries(tst-update-manager apt-pkg) |
1468 | +target_link_libraries(tst-update-manager apt-pkg ${UBUNTUONEAUTH_LDFLAGS}) |
1469 | qt5_use_modules(tst-update-manager Qml Quick Core DBus Xml Network Test) |
1470 | add_test(NAME tst-update-manager COMMAND ${XVFB_CMD} ${CMAKE_CURRENT_BINARY_DIR}/tst-update-manager) |
1471 | |
1472 | qt5_use_modules(tst-update Qml Quick Core DBus Xml Network Test) |
1473 | target_link_libraries(tst-update apt-pkg) |
1474 | add_test(NAME tst-update COMMAND ${XVFB_CMD} ${CMAKE_CURRENT_BINARY_DIR}/tst-update) |
1475 | + |
1476 | +add_custom_command( |
1477 | + TARGET tst-update-manager |
1478 | + COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_LIST_DIR}/click.result ${CMAKE_CURRENT_BINARY_DIR}/click.result |
1479 | +) |
1480 | |
1481 | === added file 'tests/plugins/system-update/click.result' |
1482 | --- tests/plugins/system-update/click.result 1970-01-01 00:00:00 +0000 |
1483 | +++ tests/plugins/system-update/click.result 2014-03-27 13:16:48 +0000 |
1484 | @@ -0,0 +1,26 @@ |
1485 | +[ |
1486 | + { |
1487 | + "framework": "ubuntu-sdk-13.10", |
1488 | + "name": "com.ubuntu.dropping-letters", |
1489 | + "title": "Dropping Letters game", |
1490 | + "version": "0.1.2.2" |
1491 | + }, |
1492 | + { |
1493 | + "framework": "ubuntu-sdk-13.10", |
1494 | + "name": "com.ubuntu.stock-ticker-mobile", |
1495 | + "title": "A stock trading app with charts, news, and management", |
1496 | + "version": "0.3.7ubuntu1" |
1497 | + }, |
1498 | + { |
1499 | + "framework": "ubuntu-sdk-13.10", |
1500 | + "name": "com.ubuntu.sudoku", |
1501 | + "title": "Sudoku game for Ubuntu devices", |
1502 | + "version": "0.4.2ubuntu2" |
1503 | + }, |
1504 | + { |
1505 | + "framework": "ubuntu-sdk-13.10", |
1506 | + "name": "com.ubuntu.developer.xda-app", |
1507 | + "title": "XDA Developers App", |
1508 | + "version": "0.4.2ubuntu2" |
1509 | + } |
1510 | +] |
1511 | |
1512 | === added file 'tests/plugins/system-update/fakenetwork.cpp' |
1513 | --- tests/plugins/system-update/fakenetwork.cpp 1970-01-01 00:00:00 +0000 |
1514 | +++ tests/plugins/system-update/fakenetwork.cpp 2014-03-27 13:16:48 +0000 |
1515 | @@ -0,0 +1,51 @@ |
1516 | +/* |
1517 | + * Copyright 2013 Canonical Ltd. |
1518 | + * |
1519 | + * This library is free software; you can redistribute it and/or |
1520 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
1521 | + * License as published by the Free Software Foundation. |
1522 | + * |
1523 | + * This program is distributed in the hope that it will be useful, |
1524 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1525 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1526 | + * General Public License for more details. |
1527 | + * |
1528 | + * You should have received a copy of the GNU Lesser General Public |
1529 | + * License along with this library; if not, write to the |
1530 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
1531 | + * Boston, MA 02110-1301, USA. |
1532 | + */ |
1533 | + |
1534 | +#include "fakenetwork.h" |
1535 | + |
1536 | +namespace UpdatePlugin { |
1537 | + |
1538 | +FakeNetwork::FakeNetwork(QObject *parent) : |
1539 | + QObject(parent) |
1540 | +{ |
1541 | +} |
1542 | + |
1543 | +void FakeNetwork::checkForNewVersions(QHash<QString, Update*> &apps) |
1544 | +{ |
1545 | + if(apps.contains("com.ubuntu.developer.xda-app")) { |
1546 | + Update* app = apps.value("com.ubuntu.developer.xda-app"); |
1547 | + QString version("0.5.2ubuntu2"); |
1548 | + app->setRemoteVersion(version); |
1549 | + emit this->updatesFound(); |
1550 | + } |
1551 | +} |
1552 | + |
1553 | +void FakeNetwork::getResourceUrl(const QString& packagename) |
1554 | +{ |
1555 | + emit this->downloadUrlFound(packagename, "http://canonical.com"); |
1556 | +} |
1557 | + |
1558 | +void FakeNetwork::getClickToken(Update* app, const QString& url, const QString& authHeader) |
1559 | +{ |
1560 | + Q_UNUSED(url); |
1561 | + Q_UNUSED(authHeader); |
1562 | + QString fakeHeader("x-click-token-header"); |
1563 | + emit this->clickTokenObtained(app, fakeHeader); |
1564 | +} |
1565 | + |
1566 | +} |
1567 | |
1568 | === added file 'tests/plugins/system-update/fakenetwork.h' |
1569 | --- tests/plugins/system-update/fakenetwork.h 1970-01-01 00:00:00 +0000 |
1570 | +++ tests/plugins/system-update/fakenetwork.h 2014-03-27 13:16:48 +0000 |
1571 | @@ -0,0 +1,49 @@ |
1572 | +/* |
1573 | + * Copyright 2013 Canonical Ltd. |
1574 | + * |
1575 | + * This library is free software; you can redistribute it and/or |
1576 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
1577 | + * License as published by the Free Software Foundation. |
1578 | + * |
1579 | + * This program is distributed in the hope that it will be useful, |
1580 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1581 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1582 | + * General Public License for more details. |
1583 | + * |
1584 | + * You should have received a copy of the GNU Lesser General Public |
1585 | + * License along with this library; if not, write to the |
1586 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
1587 | + * Boston, MA 02110-1301, USA. |
1588 | + */ |
1589 | + |
1590 | +#ifndef FAKENETWORK_H |
1591 | +#define FAKENETWORK_H |
1592 | + |
1593 | +#include <QObject> |
1594 | +#include <QHash> |
1595 | +#include <QString> |
1596 | +#include "update.h" |
1597 | + |
1598 | +namespace UpdatePlugin { |
1599 | + |
1600 | +class FakeNetwork : public QObject |
1601 | +{ |
1602 | + Q_OBJECT |
1603 | +public: |
1604 | + explicit FakeNetwork(QObject *parent = 0); |
1605 | + |
1606 | + void checkForNewVersions(QHash<QString, Update*> &apps); |
1607 | + void getResourceUrl(const QString& packagename); |
1608 | + void getClickToken(Update* app, const QString& url, const QString& authHeader); |
1609 | + |
1610 | +signals: |
1611 | + void updatesFound(); |
1612 | + void updatesNotFound(); |
1613 | + void errorOccurred(); |
1614 | + void downloadUrlFound(const QString& packagename, const QString& url); |
1615 | + void clickTokenObtained(Update* app, const QString& clickToken); |
1616 | +}; |
1617 | + |
1618 | +} |
1619 | + |
1620 | +#endif // FAKENETWORK_H |
1621 | |
1622 | === added file 'tests/plugins/system-update/fakeprocess.cpp' |
1623 | --- tests/plugins/system-update/fakeprocess.cpp 1970-01-01 00:00:00 +0000 |
1624 | +++ tests/plugins/system-update/fakeprocess.cpp 2014-03-27 13:16:48 +0000 |
1625 | @@ -0,0 +1,63 @@ |
1626 | +/* |
1627 | + * Copyright 2013 Canonical Ltd. |
1628 | + * |
1629 | + * This library is free software; you can redistribute it and/or |
1630 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
1631 | + * License as published by the Free Software Foundation. |
1632 | + * |
1633 | + * This program is distributed in the hope that it will be useful, |
1634 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1635 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1636 | + * General Public License for more details. |
1637 | + * |
1638 | + * You should have received a copy of the GNU Lesser General Public |
1639 | + * License along with this library; if not, write to the |
1640 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
1641 | + * Boston, MA 02110-1301, USA. |
1642 | + */ |
1643 | + |
1644 | +#include "fakeprocess.h" |
1645 | +#include <QFile> |
1646 | +#include <QTextStream> |
1647 | +#include <QDir> |
1648 | + |
1649 | +namespace UpdatePlugin { |
1650 | + |
1651 | +FakeProcess::FakeProcess(QObject *parent) : |
1652 | + QObject(parent) |
1653 | +{ |
1654 | +} |
1655 | + |
1656 | +void FakeProcess::start(QString command, QStringList args) |
1657 | +{ |
1658 | + Q_UNUSED(args); |
1659 | + if(command == "click") { |
1660 | + QString path = QDir::currentPath(); |
1661 | + path.append("/click.result"); |
1662 | + |
1663 | + this->m_content.clear(); |
1664 | + QFile file(path); |
1665 | + file.open(QIODevice::ReadOnly); |
1666 | + QTextStream in(&file); |
1667 | + while(!in.atEnd()) { |
1668 | + QString line = in.readLine(); |
1669 | + this->m_content.append(line); |
1670 | + } |
1671 | + |
1672 | + file.close(); |
1673 | + emit this->finished(0); |
1674 | + } |
1675 | +} |
1676 | + |
1677 | +QString FakeProcess::readAllStandardOutput() |
1678 | +{ |
1679 | + return this->m_content; |
1680 | +} |
1681 | + |
1682 | +void FakeProcess::startDetached(QString command, QStringList args) |
1683 | +{ |
1684 | + Q_UNUSED(command); |
1685 | + Q_UNUSED(args); |
1686 | +} |
1687 | + |
1688 | +} |
1689 | |
1690 | === added file 'tests/plugins/system-update/fakeprocess.h' |
1691 | --- tests/plugins/system-update/fakeprocess.h 1970-01-01 00:00:00 +0000 |
1692 | +++ tests/plugins/system-update/fakeprocess.h 2014-03-27 13:16:48 +0000 |
1693 | @@ -0,0 +1,48 @@ |
1694 | +/* |
1695 | + * Copyright 2013 Canonical Ltd. |
1696 | + * |
1697 | + * This library is free software; you can redistribute it and/or |
1698 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
1699 | + * License as published by the Free Software Foundation. |
1700 | + * |
1701 | + * This program is distributed in the hope that it will be useful, |
1702 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1703 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1704 | + * General Public License for more details. |
1705 | + * |
1706 | + * You should have received a copy of the GNU Lesser General Public |
1707 | + * License along with this library; if not, write to the |
1708 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
1709 | + * Boston, MA 02110-1301, USA. |
1710 | + */ |
1711 | + |
1712 | +#ifndef FAKEPROCESS_H |
1713 | +#define FAKEPROCESS_H |
1714 | + |
1715 | +#include <QObject> |
1716 | +#include <QString> |
1717 | +#include <QStringList> |
1718 | + |
1719 | +namespace UpdatePlugin { |
1720 | + |
1721 | +class FakeProcess : public QObject |
1722 | +{ |
1723 | + Q_OBJECT |
1724 | +public: |
1725 | + explicit FakeProcess(QObject *parent = 0); |
1726 | + |
1727 | + void start(QString command, QStringList args); |
1728 | + void startDetached(QString command, QStringList args); |
1729 | + QString readAllStandardOutput(); |
1730 | + |
1731 | +signals: |
1732 | + void finished(int); |
1733 | + |
1734 | +private: |
1735 | + QString m_content; |
1736 | + |
1737 | +}; |
1738 | + |
1739 | +} |
1740 | + |
1741 | +#endif // FAKEPROCESS_H |
1742 | |
1743 | === added file 'tests/plugins/system-update/fakessoservice.cpp' |
1744 | --- tests/plugins/system-update/fakessoservice.cpp 1970-01-01 00:00:00 +0000 |
1745 | +++ tests/plugins/system-update/fakessoservice.cpp 2014-03-27 13:16:48 +0000 |
1746 | @@ -0,0 +1,16 @@ |
1747 | +#include "fakessoservice.h" |
1748 | + |
1749 | +namespace UpdatePlugin { |
1750 | + |
1751 | +FakeSsoService::FakeSsoService(QObject *parent) : |
1752 | + QObject(parent) |
1753 | +{ |
1754 | +} |
1755 | + |
1756 | +void FakeSsoService::getCredentials() |
1757 | +{ |
1758 | + Token token("token_key", "token_secret", "consumer_key", "consumer_secret"); |
1759 | + emit this->credentialsFound(token); |
1760 | +} |
1761 | + |
1762 | +} |
1763 | |
1764 | === added file 'tests/plugins/system-update/fakessoservice.h' |
1765 | --- tests/plugins/system-update/fakessoservice.h 1970-01-01 00:00:00 +0000 |
1766 | +++ tests/plugins/system-update/fakessoservice.h 2014-03-27 13:16:48 +0000 |
1767 | @@ -0,0 +1,27 @@ |
1768 | +#ifndef FAKESSOSERVICE_H |
1769 | +#define FAKESSOSERVICE_H |
1770 | + |
1771 | +#include <QObject> |
1772 | +#include <token.h> |
1773 | + |
1774 | +using namespace UbuntuOne; |
1775 | + |
1776 | +namespace UpdatePlugin { |
1777 | + |
1778 | +class FakeSsoService : public QObject |
1779 | +{ |
1780 | + Q_OBJECT |
1781 | +public: |
1782 | + explicit FakeSsoService(QObject *parent = 0); |
1783 | + |
1784 | + void getCredentials(); |
1785 | + |
1786 | +signals: |
1787 | + void credentialsFound(const Token&); |
1788 | + void credentialsNotFound(); |
1789 | + |
1790 | +}; |
1791 | + |
1792 | +} |
1793 | + |
1794 | +#endif // FAKESSOSERVICE_H |
1795 | |
1796 | === added file 'tests/plugins/system-update/fakesystemupdate.cpp' |
1797 | --- tests/plugins/system-update/fakesystemupdate.cpp 1970-01-01 00:00:00 +0000 |
1798 | +++ tests/plugins/system-update/fakesystemupdate.cpp 2014-03-27 13:16:48 +0000 |
1799 | @@ -0,0 +1,28 @@ |
1800 | +/* |
1801 | + * Copyright 2014 Canonical Ltd. |
1802 | + * |
1803 | + * This library is free software; you can redistribute it and/or |
1804 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
1805 | + * License as published by the Free Software Foundation. |
1806 | + * |
1807 | + * This program is distributed in the hope that it will be useful, |
1808 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1809 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1810 | + * General Public License for more details. |
1811 | + * |
1812 | + * You should have received a copy of the GNU Lesser General Public |
1813 | + * License along with this library; if not, write to the |
1814 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
1815 | + * Boston, MA 02110-1301, USA. |
1816 | + */ |
1817 | + |
1818 | +#include "fakesystemupdate.h" |
1819 | + |
1820 | +namespace UpdatePlugin { |
1821 | + |
1822 | +FakeSystemUpdate::FakeSystemUpdate(QObject *parent) : |
1823 | + QObject(parent) |
1824 | +{ |
1825 | +} |
1826 | + |
1827 | +} |
1828 | |
1829 | === added file 'tests/plugins/system-update/fakesystemupdate.h' |
1830 | --- tests/plugins/system-update/fakesystemupdate.h 1970-01-01 00:00:00 +0000 |
1831 | +++ tests/plugins/system-update/fakesystemupdate.h 2014-03-27 13:16:48 +0000 |
1832 | @@ -0,0 +1,58 @@ |
1833 | +/* |
1834 | + * Copyright 2014 Canonical Ltd. |
1835 | + * |
1836 | + * This library is free software; you can redistribute it and/or |
1837 | + * modify it under the terms of version 3 of the GNU Lesser General Public |
1838 | + * License as published by the Free Software Foundation. |
1839 | + * |
1840 | + * This program is distributed in the hope that it will be useful, |
1841 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
1842 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
1843 | + * General Public License for more details. |
1844 | + * |
1845 | + * You should have received a copy of the GNU Lesser General Public |
1846 | + * License along with this library; if not, write to the |
1847 | + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
1848 | + * Boston, MA 02110-1301, USA. |
1849 | + */ |
1850 | + |
1851 | +#ifndef FAKESYSTEMUPDATE_H |
1852 | +#define FAKESYSTEMUPDATE_H |
1853 | + |
1854 | +#include <QObject> |
1855 | +#include "../../../plugins/system-update/update.h" |
1856 | + |
1857 | +namespace UpdatePlugin { |
1858 | + |
1859 | +class FakeSystemUpdate: public QObject |
1860 | +{ |
1861 | + Q_OBJECT |
1862 | +public: |
1863 | + explicit FakeSystemUpdate(QObject *parent = 0); |
1864 | + ~FakeSystemUpdate() {} |
1865 | + |
1866 | + int downloadMode() { return 0; } |
1867 | + void setDownloadMode(int) {} |
1868 | + int currentBuildNumber() { return 123;} |
1869 | + |
1870 | + void checkForUpdate() {} |
1871 | + void downloadUpdate() {} |
1872 | + void applyUpdate() {} |
1873 | + void cancelUpdate() {} |
1874 | + void pauseDownload() {} |
1875 | + |
1876 | +Q_SIGNALS: |
1877 | + void updateAvailable(const QString& packageName, Update *update); |
1878 | + void updateNotFound(); |
1879 | + void updateProgress(int percentage, double eta); |
1880 | + void updatePaused(int percentage); |
1881 | + void updateDownloaded(); |
1882 | + void updateFailed(int consecutiveFailureCount, QString lastReason); |
1883 | + void downloadModeChanged(); |
1884 | + void updateProcessFailed(const QString& reason); |
1885 | + |
1886 | +}; |
1887 | + |
1888 | +} |
1889 | + |
1890 | +#endif // FAKESYSTEMUPDATE_H |
1891 | |
1892 | === modified file 'tests/plugins/system-update/tst_updatemanager.cpp' |
1893 | --- tests/plugins/system-update/tst_updatemanager.cpp 2014-02-26 11:39:47 +0000 |
1894 | +++ tests/plugins/system-update/tst_updatemanager.cpp 2014-03-27 13:16:48 +0000 |
1895 | @@ -33,6 +33,8 @@ |
1896 | void testRegisterSystemUpdateNotRequired(); |
1897 | void testStartDownload(); |
1898 | void testPauseDownload(); |
1899 | + void testCheckUpdatesModelSignal(); |
1900 | + void testCheckUpdatesUpdateSignal(); |
1901 | |
1902 | private: |
1903 | Update* getUpdate(); |
1904 | @@ -120,6 +122,34 @@ |
1905 | QTRY_COMPARE(update->updateState(), false); |
1906 | } |
1907 | |
1908 | +void UpdateManagerTest::testCheckUpdatesModelSignal() |
1909 | +{ |
1910 | + UpdateManager manager; |
1911 | + QSignalSpy spy(&manager, SIGNAL(modelChanged())); |
1912 | + QTRY_COMPARE(manager.get_apps().size(), 0); |
1913 | + manager.checkUpdates(); |
1914 | + QTRY_COMPARE(manager.get_apps().size(), 4); |
1915 | + QTRY_COMPARE(manager.get_model().size(), 1); |
1916 | + Update* app = manager.get_model()[0].value<Update*>(); |
1917 | + QTRY_COMPARE(app->getTitle(), QString("XDA Developers App")); |
1918 | + QTRY_COMPARE(app->updateRequired(), true); |
1919 | + QTRY_COMPARE(app->getPackageName(), QString("com.ubuntu.developer.xda-app")); |
1920 | +} |
1921 | + |
1922 | +void UpdateManagerTest::testCheckUpdatesUpdateSignal() |
1923 | +{ |
1924 | + UpdateManager manager; |
1925 | + QSignalSpy spy(&manager, SIGNAL(updateAvailableFound())); |
1926 | + QTRY_COMPARE(manager.get_apps().size(), 0); |
1927 | + manager.checkUpdates(); |
1928 | + QTRY_COMPARE(manager.get_apps().size(), 4); |
1929 | + QTRY_COMPARE(manager.get_model().size(), 1); |
1930 | + Update* app = manager.get_model()[0].value<Update*>(); |
1931 | + QTRY_COMPARE(app->getTitle(), QString("XDA Developers App")); |
1932 | + QTRY_COMPARE(app->updateRequired(), true); |
1933 | + QTRY_COMPARE(app->getPackageName(), QString("com.ubuntu.developer.xda-app")); |
1934 | +} |
1935 | + |
1936 | |
1937 | QTEST_MAIN(UpdateManagerTest); |
1938 | #include "tst_updatemanager.moc" |
FAILED: Continuous integration, rev:636 jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- ci/662/ jenkins. qa.ubuntu. com/job/ generic- mediumtests- trusty/ 3559/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- trusty- touch/3168/ console jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- trusty- amd64-ci/ 178/console jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- trusty- armhf-ci/ 166/console jenkins. qa.ubuntu. com/job/ ubuntu- system- settings- trusty- i386-ci/ 165/console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- trusty- amd64/3563/ console jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- trusty- armhf/3170/ console
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- system- settings- ci/662/ rebuild
http://