Merge lp:~michihenning/storage-framework/merge-devel into lp:storage-framework

Proposed by Michi Henning
Status: Merged
Approved by: James Henstridge
Approved revision: no longer in the source branch.
Merged at revision: 15
Proposed branch: lp:~michihenning/storage-framework/merge-devel
Merge into: lp:storage-framework
Diff against target: 3789 lines (+1688/-685)
66 files modified
CMakeLists.txt (+2/-1)
data/registry.xml (+21/-24)
debian/changelog (+9/-0)
debian/control (+5/-90)
debian/control.in (+15/-2)
debian/storage-framework-registry.install (+2/-0)
demo/demo.qml (+1/-1)
demo/provider_test/provider-test.cpp (+1/-1)
include/unity/storage/internal/AccountDetails.h (+60/-0)
include/unity/storage/internal/ActivityNotifier.h (+57/-0)
include/unity/storage/internal/EnvVars.h (+51/-0)
include/unity/storage/internal/InactivityTimer.h (+60/-0)
include/unity/storage/internal/TraceMessageHandler.h (+3/-0)
include/unity/storage/qt/Account.h (+4/-1)
include/unity/storage/qt/AccountsJob.h (+2/-5)
include/unity/storage/qt/Runtime.h (+3/-3)
include/unity/storage/qt/internal/AccountImpl.h (+6/-19)
include/unity/storage/qt/internal/AccountsJobImpl.h (+18/-10)
include/unity/storage/qt/internal/Handler.h (+2/-2)
include/unity/storage/qt/internal/RuntimeImpl.h (+7/-8)
include/unity/storage/registry/Registry.h (+35/-0)
include/unity/storage/registry/internal/ListAccountsHandler.h (+70/-0)
include/unity/storage/registry/internal/RegistryAdaptor.h (+71/-0)
include/unity/storage/registry/internal/qdbus-last-error-msg.h (+41/-0)
src/CMakeLists.txt (+1/-0)
src/internal/AccountDetails.cpp (+108/-0)
src/internal/CMakeLists.txt (+8/-0)
src/internal/EnvVars.cpp (+81/-0)
src/internal/InactivityTimer.cpp (+82/-0)
src/internal/TraceMessageHandler.cpp (+20/-3)
src/qt/Account.cpp (+10/-0)
src/qt/AccountsJob.cpp (+2/-8)
src/qt/CMakeLists.txt (+10/-3)
src/qt/Runtime.cpp (+4/-4)
src/qt/client/internal/remote_client/RuntimeImpl.cpp (+1/-1)
src/qt/internal/AccountImpl.cpp (+27/-49)
src/qt/internal/AccountsJobImpl.cpp (+50/-69)
src/qt/internal/ItemImpl.cpp (+10/-8)
src/qt/internal/ItemListJobImpl.cpp (+4/-6)
src/qt/internal/MultiItemListJobImpl.cpp (+1/-4)
src/qt/internal/RuntimeImpl.cpp (+24/-22)
src/qt/internal/validate.cpp (+75/-63)
src/registry/CMakeLists.txt (+47/-0)
src/registry/com.canonical.StorageFramework.Registry.service.in (+3/-0)
src/registry/internal/ListAccountsHandler.cpp (+127/-0)
src/registry/internal/RegistryAdaptor.cpp (+55/-0)
src/registry/internal/qdbus-last-error-msg.cpp (+49/-0)
src/registry/main.cpp (+95/-0)
tests/CMakeLists.txt (+1/-6)
tests/copyright/check_copyright.sh (+13/-7)
tests/headers/CMakeLists.txt (+2/-2)
tests/headers/compile_headers.py (+11/-8)
tests/local-client/local-client_test.cpp (+4/-0)
tests/provider-AccountData/AccountData_test.cpp (+4/-0)
tests/provider-DBusPeerCache/DBusPeerCache_test.cpp (+4/-0)
tests/provider-ProviderInterface/TestProvider.cpp (+5/-5)
tests/registry/CMakeLists.txt (+20/-0)
tests/registry/registry_test.cpp (+27/-0)
tests/remote-client-v1/remote-client-v1_test.cpp (+4/-4)
tests/remote-client/CMakeLists.txt (+1/-1)
tests/remote-client/remote-client_test.cpp (+131/-81)
tests/utils/DBusEnvironment.cpp (+9/-0)
tests/utils/DBusEnvironment.h (+1/-0)
tests/utils/ProviderFixture.h (+4/-0)
tests/utils/com.ubuntu.OnlineAccounts.Manager.xml (+0/-153)
tests/utils/fake-online-accounts-daemon.py (+7/-11)
To merge this branch: bzr merge lp:~michihenning/storage-framework/merge-devel
Reviewer Review Type Date Requested Status
James Henstridge Approve
Review via email: mp+312873@code.launchpad.net

Commit message

Merge devel at r99. Updated changelog.

Description of the change

Merged devel at r99. Updated changelog.

To post a comment you must log in.
15. By CI Train Bot Account

* Fix for lp:1644577, fail list job if metadata for any item is incorrect.
* Always emit itemsReady(), even if list is empty.
* Improvements to error logging and detail in error messages: lp:1644577
* Added separate registry service.

Revision history for this message
James Henstridge (jamesh) wrote :

Looks good.

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2016-10-31 09:03:32 +0000
3+++ CMakeLists.txt 2016-12-12 02:53:43 +0000
4@@ -104,7 +104,7 @@
5 include(CTest)
6 enable_testing()
7
8-include(EnableCoverageReport)
9+find_package(CoverageReport)
10
11 include(GNUInstallDirs)
12
13@@ -138,6 +138,7 @@
14 storage-framework-qt-local-client
15 sf-provider-objects
16 storage-framework-provider
17+ storage-framework-registry
18 FILTER
19 ${CMAKE_SOURCE_DIR}/tests/*
20 ${CMAKE_BINARY_DIR}/*
21
22=== modified file 'data/registry.xml'
23--- data/registry.xml 2016-05-04 14:32:07 +0000
24+++ data/registry.xml 2016-12-12 02:53:43 +0000
25@@ -3,33 +3,30 @@
26 <node xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
27 <!--
28 com.canonical.StorageFramework.Registry:
29- @short_description: Interface to query the backend registry
30-
31- Inteface to query the repository of backends that are
32- available.
33+ @short_description: Interface to retrieve providers that are configured in online accounts
34 -->
35 <interface name="com.canonical.StorageFramework.Registry">
36-
37 <!--
38- GetBackend:
39- @short_description: request access to a storage account
40- @service_id: if not empty, restrict results to accounts
41- matching this service ID.
42- @bus_name: the bus name of the storage provider
43- @path: the object path of the storage account at the provider
44-
45- Interactively prompt the user to pick a storage account for
46- use by the application, and return the D-Bus endpoint that can
47- be used to communicate with the associated provider.
48-
49- As this involves user interaction, the caller should use a
50- relatively long time out for this method call.
51- -->
52- <method name="GetProvider">
53- <arg type="s" name="service_id" direction="in" />
54-
55- <arg type="s" name="bus_name" direction="out" />
56- <arg type="o" name="path" direction="out" />
57+ List:
58+ @short_description: Get the list of accounts
59+ @accounts: Returned list of accounts.
60+
61+ Returns the list of provider accounts that are available
62+ in online accounts. In essence, this method is a proxy
63+ for the OnlineAccounts::Manager::availableAccounts() method.
64+
65+ The returned values are structs with the following members:
66+ - bus name (e.g. "com.canonical.StorageFramework.Provider.OwnCloud")
67+ - object path (e.g. "/provider/7")
68+ - ID (e.g. 7, used for object path)
69+ - service ID (e.g. "storage-provider-owncloud")
70+ - display name (e.g. "michi.henning@canonical.com")
71+ - translated provider name (e.g. "OwnCloud")
72+ - icon name
73+ -->
74+ <method name="ListAccounts">
75+ <arg type="a(soussss)" name="accounts" direction="out"/>
76+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;unity::storage::internal::AccountDetails&gt;"/>
77 </method>
78 </interface>
79 </node>
80
81=== modified file 'debian/changelog'
82--- debian/changelog 2016-11-04 12:22:33 +0000
83+++ debian/changelog 2016-12-12 02:53:43 +0000
84@@ -1,3 +1,12 @@
85+storage-framework (0.2+17.04.20161104-0ubuntu2) UNRELEASED; urgency=medium
86+
87+ * Fix for lp:1644577, fail list job if metadata for any item is incorrect.
88+ * Always emit itemsReady(), even if list is empty.
89+ * Improvements to error logging and detail in error messages: lp:1644577
90+ * Added separate registry service.
91+
92+ -- Michi Henning <michi.henning@canonical.com> Fri, 09 Dec 2016 11:35:17 +1000
93+
94 storage-framework (0.2+17.04.20161104-0ubuntu1) zesty; urgency=medium
95
96 [ Michi Henning ]
97
98=== modified file 'debian/control'
99--- debian/control 2016-11-04 12:22:33 +0000
100+++ debian/control 2016-12-12 02:53:43 +0000
101@@ -1,98 +1,13 @@
102 # This file is autogenerated. DO NOT EDIT!
103 #
104 # Modifications should be made to ./debian/control.in instead.
105-# This file is regenerated automatically in the clean target.
106+# This file is regenerated automatically by bileto.
107 #
108 Source: storage-framework
109-Section: libs
110-Priority: optional
111-Maintainer: Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
112-Standards-Version: 3.9.6
113-Build-Depends: cmake,
114- cmake-extras (>= 0.4),
115- debhelper (>= 9),
116- devscripts,
117- doxygen,
118- google-mock,
119- libapparmor-dev,
120- libboost-filesystem-dev (>= 1.58) | libboost-filesystem1.58-dev,
121- libboost-system-dev (>= 1.58) | libboost-system1.58-dev,
122- libboost-thread-dev (>= 1.58) | libboost-thread1.58-dev,
123- libglib2.0-dev,
124- libgtest-dev,
125- libonline-accounts-qt-dev,
126- libqtdbustest1-dev,
127- libunity-api-dev,
128- lsb-release,
129- python3-dbus,
130- python3-gi,
131- qtbase5-dev,
132- qtbase5-dev-tools,
133- qtdeclarative5-dev,
134-Homepage: https://launchpad.net/storage-framework
135-# if you don't have have commit access to this branch but would like to upload
136-# directly to Ubuntu, don't worry: your changes will be merged back into the
137-# upstream branch
138-Vcs-Bzr: lp:storage-framework
139+
140+# DO NOT EDIT THIS FILE. WE REALLY MEAN IT!
141
142 Package: libstorage-framework-provider-1-5
143 Architecture: any
144-Multi-Arch: same
145-Pre-Depends: ${misc:Pre-Depends},
146-Depends: ${misc:Depends},
147- ${shlibs:Depends},
148-Description: Library for Storage Framework providers
149- Server-side runtime support for provider implementations.
150-
151-Package: libstorage-framework-qt-client-1-0
152-Architecture: any
153-Multi-Arch: same
154-Pre-Depends: ${misc:Pre-Depends},
155-Depends: ${misc:Depends},
156- ${shlibs:Depends},
157-Description: Client library for the Storage Framework (API v1, soon to be removed)
158- Runtime support for storage framework clients.
159-
160-Package: libstorage-framework-qt-client-2-0
161-Architecture: any
162-Multi-Arch: same
163-Pre-Depends: ${misc:Pre-Depends},
164-Depends: ${misc:Depends},
165- ${shlibs:Depends},
166-Description: Client library for the Storage Framework
167- Runtime support for storage framework clients.
168-
169-Package: libstorage-framework-qt-local-client-1-0
170-Architecture: any
171-Multi-Arch: same
172-Pre-Depends: ${misc:Pre-Depends},
173-Depends: ${misc:Depends},
174- ${shlibs:Depends},
175-Description: Client library for the Storage Framework backed by the local file system
176- A version of the client-side API that implements a local
177- file system provider. This is intended mainly for testing;
178- it allows application code to use the storage framework
179- API without requiring use of DBus and cloud service account.
180-
181-Package: storage-framework-client-dev
182-Section: libdevel
183-Architecture: any
184-Multi-Arch: same
185-Pre-Depends: ${misc:Pre-Depends},
186-Depends: libstorage-framework-qt-client-1-0 (= ${binary:Version}),
187- libstorage-framework-qt-local-client-1-0 (= ${binary:Version}),
188- qtbase5-dev,
189- ${misc:Depends},
190-Description: Header files for the Storage Framework client libraries
191- Development C++ headers for the client side API.
192-
193-Package: storage-framework-provider-dev
194-Section: libdevel
195-Architecture: any
196-Multi-Arch: same
197-Pre-Depends: ${misc:Pre-Depends},
198-Depends: libstorage-framework-provider-1-5 (= ${binary:Version}),
199- libboost-thread-dev (>= 1.58) | libboost-thread1.58-dev,
200- ${misc:Depends},
201-Description: Header files for the Storage Framework provider library
202- Development C++ headers for the provider API.
203+Description: DO NOT EDIT THIS FILE, IT IS GENERATED FROM control.in
204+ DO NOT EDIT THIS FILE
205
206=== modified file 'debian/control.in'
207--- debian/control.in 2016-09-30 01:47:57 +0000
208+++ debian/control.in 2016-12-12 02:53:43 +0000
209@@ -4,9 +4,8 @@
210 Maintainer: Ubuntu Core Developers <ubuntu-devel-discuss@lists.ubuntu.com>
211 Standards-Version: 3.9.6
212 Build-Depends: cmake,
213- cmake-extras (>= 0.4),
214+ cmake-extras (>= 0.10),
215 debhelper (>= 9),
216- devscripts,
217 doxygen,
218 google-mock,
219 libapparmor-dev,
220@@ -18,6 +17,7 @@
221 libonline-accounts-qt-dev,
222 libqtdbustest1-dev,
223 libunity-api-dev,
224+ licensecheck | devscripts (<< 2.16.6),
225 lsb-release,
226 python3-dbus,
227 python3-gi,
228@@ -48,12 +48,24 @@
229 Description: Client library for the Storage Framework (API v1, soon to be removed)
230 Runtime support for storage framework clients.
231
232+Package: storage-framework-registry
233+Architecture: any
234+Multi-Arch: foreign
235+Pre-Depends: ${misc:Pre-Depends},
236+Depends: ${misc:Depends},
237+ ${shlibs:Depends},
238+# TODO: should be removed once online accounts is fixed: lp:1643421
239+ online-accounts-daemon,
240+Description: Registry for the Storage Framework
241+ DBus service that provides access to provider account information.
242+
243 Package: libstorage-framework-qt-client-2-0
244 Architecture: any
245 Multi-Arch: same
246 Pre-Depends: ${misc:Pre-Depends},
247 Depends: ${misc:Depends},
248 ${shlibs:Depends},
249+ storage-framework-registry
250 Description: Client library for the Storage Framework
251 Runtime support for storage framework clients.
252
253@@ -76,6 +88,7 @@
254 Pre-Depends: ${misc:Pre-Depends},
255 Depends: libstorage-framework-qt-client-1-0 (= ${binary:Version}),
256 libstorage-framework-qt-local-client-1-0 (= ${binary:Version}),
257+ libstorage-framework-qt-client-2-0 (= ${binary:Version}),
258 qtbase5-dev,
259 ${misc:Depends},
260 Description: Header files for the Storage Framework client libraries
261
262=== added file 'debian/storage-framework-registry.install'
263--- debian/storage-framework-registry.install 1970-01-01 00:00:00 +0000
264+++ debian/storage-framework-registry.install 2016-12-12 02:53:43 +0000
265@@ -0,0 +1,2 @@
266+usr/lib/*/*/storage-framework-registry
267+usr/share/dbus-1/services/com.canonical.StorageFramework.Registry.service
268
269=== modified file 'demo/demo.qml'
270--- demo/demo.qml 2016-11-04 10:52:10 +0000
271+++ demo/demo.qml 2016-12-12 02:53:43 +0000
272@@ -48,7 +48,7 @@
273 for (var i = 0; i < accounts.length; i++) {
274 console.log("Account " + i + ": busName = " + accounts[i].busName());
275 console.log("Account " + i + ": objectPath = " + accounts[i].objectPath());
276- console.log("Account " + i + ": displayName = " + accounts[i].displayName);
277+ console.log("Account " + i + ": name = " + accounts[i].name);
278 }
279 }
280 }
281
282=== modified file 'demo/provider_test/provider-test.cpp'
283--- demo/provider_test/provider-test.cpp 2016-11-03 02:43:43 +0000
284+++ demo/provider_test/provider-test.cpp 2016-12-12 02:53:43 +0000
285@@ -314,7 +314,7 @@
286 int main(int argc, char **argv)
287 {
288 const std::string bus_name = "com.canonical.StorageFramework.Provider.ProviderTest";
289- std::string account_service_id = "google-drive-scope";
290+ std::string account_service_id = "storage-provider-test";
291 if (argc > 1)
292 {
293 account_service_id = argv[1];
294
295=== added file 'include/unity/storage/internal/AccountDetails.h'
296--- include/unity/storage/internal/AccountDetails.h 1970-01-01 00:00:00 +0000
297+++ include/unity/storage/internal/AccountDetails.h 2016-12-12 02:53:43 +0000
298@@ -0,0 +1,60 @@
299+/*
300+ * Copyright (C) 2016 Canonical Ltd
301+ *
302+ * This program is free software: you can redistribute it and/or modify
303+ * it under the terms of the GNU Lesser General Public License version 3 as
304+ * published by the Free Software Foundation.
305+ *
306+ * This program is distributed in the hope that it will be useful,
307+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
308+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
309+ * GNU Lesser General Public License for more details.
310+ *
311+ * You should have received a copy of the GNU Lesser General Public License
312+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
313+ *
314+ * Authors: Michi Henning <michi.henning@canonical.com>
315+ */
316+
317+#pragma once
318+
319+#pragma GCC diagnostic push
320+#pragma GCC diagnostic ignored "-Wcast-align"
321+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
322+#pragma GCC diagnostic ignored "-Wswitch-default"
323+#include <QDBusArgument>
324+#pragma GCC diagnostic pop
325+
326+namespace unity
327+{
328+namespace storage
329+{
330+namespace internal
331+{
332+
333+struct AccountDetails
334+{
335+ QString busName;
336+ QDBusObjectPath objectPath;
337+ quint32 id;
338+ QString serviceId;
339+ QString displayName;
340+ QString providerName;
341+ QString iconName;
342+};
343+
344+bool operator==(AccountDetails const& lhs, AccountDetails const& rhs);
345+bool operator!=(AccountDetails const& lhs, AccountDetails const& rhs);
346+bool operator<(AccountDetails const& lhs, AccountDetails const& rhs);
347+bool operator<=(AccountDetails const& lhs, AccountDetails const& rhs);
348+bool operator>(AccountDetails const& lhs, AccountDetails const& rhs);
349+bool operator>=(AccountDetails const& lhs, AccountDetails const& rhs);
350+
351+QDBusArgument& operator<<(QDBusArgument& argument, storage::internal::AccountDetails const& account);
352+QDBusArgument const& operator>>(QDBusArgument const& argument, storage::internal::AccountDetails& account);
353+
354+} // namespace internal
355+} // namespace storage
356+} // namespace unity
357+
358+Q_DECLARE_METATYPE(unity::storage::internal::AccountDetails)
359
360=== added file 'include/unity/storage/internal/ActivityNotifier.h'
361--- include/unity/storage/internal/ActivityNotifier.h 1970-01-01 00:00:00 +0000
362+++ include/unity/storage/internal/ActivityNotifier.h 2016-12-12 02:53:43 +0000
363@@ -0,0 +1,57 @@
364+/*
365+ * Copyright (C) 2016 Canonical Ltd
366+ *
367+ * This program is free software: you can redistribute it and/or modify
368+ * it under the terms of the GNU Lesser General Public License version 3 as
369+ * published by the Free Software Foundation.
370+ *
371+ * This program is distributed in the hope that it will be useful,
372+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
373+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
374+ * GNU Lesser General Public License for more details.
375+ *
376+ * You should have received a copy of the GNU Lesser General Public License
377+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
378+ *
379+ * Authors: Michi Henning <michi.henning@canonical.com>
380+ */
381+
382+#pragma once
383+
384+#include <unity/storage/internal/InactivityTimer.h>
385+
386+#include <cassert>
387+#include <memory>
388+
389+namespace unity
390+{
391+namespace storage
392+{
393+namespace internal
394+{
395+
396+class InactivityTimer;
397+
398+class ActivityNotifier
399+{
400+public:
401+ ActivityNotifier(std::shared_ptr<InactivityTimer> const& timer)
402+ : timer_(timer)
403+ {
404+ assert(timer);
405+
406+ timer_->request_started();
407+ }
408+
409+ ~ActivityNotifier()
410+ {
411+ timer_->request_finished();
412+ }
413+
414+private:
415+ std::shared_ptr<InactivityTimer> timer_;
416+};
417+
418+} // namespace internal
419+} // namespace storage
420+} // namespace unity
421
422=== added file 'include/unity/storage/internal/EnvVars.h'
423--- include/unity/storage/internal/EnvVars.h 1970-01-01 00:00:00 +0000
424+++ include/unity/storage/internal/EnvVars.h 2016-12-12 02:53:43 +0000
425@@ -0,0 +1,51 @@
426+/*
427+ * Copyright (C) 2016 Canonical Ltd
428+ *
429+ * This program is free software: you can redistribute it and/or modify
430+ * it under the terms of the GNU Lesser General Public License version 3 as
431+ * published by the Free Software Foundation.
432+ *
433+ * This program is distributed in the hope that it will be useful,
434+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
435+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
436+ * GNU Lesser General Public License for more details.
437+ *
438+ * You should have received a copy of the GNU Lesser General Public License
439+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
440+ *
441+ * Authors: Michi Henning <michi.henning@canonical.com>
442+ */
443+
444+#pragma once
445+
446+#include <unity/storage/registry/Registry.h>
447+
448+#include <string>
449+
450+namespace unity
451+{
452+namespace storage
453+{
454+namespace internal
455+{
456+
457+constexpr char const* REGISTRY_IDLE_TIMEOUT = "SF_REGISTRY_IDLE_TIMEOUT"; // Seconds, 0 means "never"
458+constexpr int REGISTRY_IDLE_TIMEOUT_DFLT = 30;
459+
460+// Helper class to make retrieval of environment variables type-safe and
461+// to sanity check the setting, if applicable. Also returns a default
462+// setting, if applicable.
463+
464+class EnvVars
465+{
466+public:
467+ static int registry_timeout_ms();
468+
469+ // Returns value of var_name in the environment, if set, and an empty string otherwise.
470+ // Can be used for any environment variable, not just the ones defined above.
471+ static std::string get(char const* var_name);
472+};
473+
474+} // namespace internal
475+} // namespace storage
476+} // namespace unity
477
478=== added file 'include/unity/storage/internal/InactivityTimer.h'
479--- include/unity/storage/internal/InactivityTimer.h 1970-01-01 00:00:00 +0000
480+++ include/unity/storage/internal/InactivityTimer.h 2016-12-12 02:53:43 +0000
481@@ -0,0 +1,60 @@
482+/*
483+ * Copyright (C) 2016 Canonical Ltd
484+ *
485+ * This program is free software: you can redistribute it and/or modify
486+ * it under the terms of the GNU Lesser General Public License version 3 as
487+ * published by the Free Software Foundation.
488+ *
489+ * This program is distributed in the hope that it will be useful,
490+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
491+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
492+ * GNU Lesser General Public License for more details.
493+ *
494+ * You should have received a copy of the GNU Lesser General Public License
495+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
496+ *
497+ * Authors: Michi Henning <michi.henning@canonical.com>
498+ */
499+
500+#pragma once
501+
502+#pragma GCC diagnostic push
503+#pragma GCC diagnostic ignored "-Wcast-align"
504+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
505+#pragma GCC diagnostic ignored "-Wswitch-default"
506+#include <QTimer>
507+#pragma GCC diagnostic pop
508+
509+#include <functional>
510+
511+namespace unity
512+{
513+namespace storage
514+{
515+namespace internal
516+{
517+
518+class InactivityTimer : public QObject
519+{
520+ Q_OBJECT
521+
522+public:
523+ InactivityTimer(int timeout_ms, std::function<void()> timeout_func);
524+ ~InactivityTimer();
525+
526+ void request_started();
527+ void request_finished();
528+
529+private Q_SLOTS:
530+ void timeout();
531+
532+private:
533+ int timeout_ms_;
534+ std::function<void()> timeout_func_;
535+ QTimer timer_;
536+ int32_t num_requests_;
537+};
538+
539+} // namespace internal
540+} // namespace storage
541+} // namespace unity
542
543=== modified file 'include/unity/storage/internal/TraceMessageHandler.h'
544--- include/unity/storage/internal/TraceMessageHandler.h 2016-08-25 05:18:37 +0000
545+++ include/unity/storage/internal/TraceMessageHandler.h 2016-12-12 02:53:43 +0000
546@@ -35,7 +35,10 @@
547 class TraceMessageHandler final
548 {
549 public:
550+ TraceMessageHandler();
551 TraceMessageHandler(std::string const& prog_name);
552+ TraceMessageHandler(QString const& prog_name);
553+ TraceMessageHandler(char const* prog_name);
554 ~TraceMessageHandler();
555
556 private:
557
558=== modified file 'include/unity/storage/qt/Account.h'
559--- include/unity/storage/qt/Account.h 2016-11-03 06:41:00 +0000
560+++ include/unity/storage/qt/Account.h 2016-12-12 02:53:43 +0000
561@@ -47,6 +47,8 @@
562 Q_PROPERTY(QString busName READ busName FINAL)
563 Q_PROPERTY(QString objectPath READ objectPath FINAL)
564 Q_PROPERTY(QString displayName READ displayName FINAL)
565+ Q_PROPERTY(QString providerName READ providerName FINAL)
566+ Q_PROPERTY(QString iconName READ iconName FINAL)
567
568 public:
569 Account();
570@@ -60,7 +62,8 @@
571 QString busName() const;
572 QString objectPath() const;
573 QString displayName() const;
574- // TODO: add more methods to retrieve additional info, such as description, icon ID, and service name.
575+ QString providerName() const;
576+ QString iconName() const;
577
578 Q_INVOKABLE unity::storage::qt::ItemListJob* roots(QStringList const& keys = QStringList()) const;
579 Q_INVOKABLE unity::storage::qt::ItemJob* get(QString const& itemId, QStringList const& keys = QStringList()) const;
580
581=== modified file 'include/unity/storage/qt/AccountsJob.h'
582--- include/unity/storage/qt/AccountsJob.h 2016-11-02 02:54:48 +0000
583+++ include/unity/storage/qt/AccountsJob.h 2016-12-12 02:53:43 +0000
584@@ -34,12 +34,10 @@
585 {
586
587 class AccountsJobImpl;
588-class RuntimeImpl;
589
590 } // namespace internal
591
592 class Account;
593-class Runtime;
594 class StorageError;
595
596 class Q_DECL_EXPORT AccountsJob final : public QObject
597@@ -65,14 +63,13 @@
598 void statusChanged(unity::storage::qt::AccountsJob::Status status) const;
599
600 private:
601- AccountsJob(std::shared_ptr<internal::RuntimeImpl> const& runtime);
602- AccountsJob(StorageError const& error);
603+ AccountsJob(std::unique_ptr<internal::AccountsJobImpl> accounts_job_impl);
604
605 QVariantList accountsAsVariantList() const;
606
607 std::unique_ptr<internal::AccountsJobImpl> const p_;
608
609- friend class internal::RuntimeImpl;
610+ friend class internal::AccountsJobImpl;
611 };
612
613 } // namespace qt
614
615=== modified file 'include/unity/storage/qt/Runtime.h'
616--- include/unity/storage/qt/Runtime.h 2016-11-02 02:54:48 +0000
617+++ include/unity/storage/qt/Runtime.h 2016-12-12 02:53:43 +0000
618@@ -66,9 +66,9 @@
619
620 Account make_test_account(QString const& bus_name,
621 QString const& object_path,
622- QString const& id = "",
623- QString const& serviceId = "",
624- QString const& displayName = "") const;
625+ quint32 id = 999,
626+ QString const& service_id = "",
627+ QString const& name = "") const;
628
629 private:
630 std::shared_ptr<internal::RuntimeImpl> p_;
631
632=== modified file 'include/unity/storage/qt/internal/AccountImpl.h'
633--- include/unity/storage/qt/internal/AccountImpl.h 2016-11-03 06:41:00 +0000
634+++ include/unity/storage/qt/internal/AccountImpl.h 2016-12-12 02:53:43 +0000
635@@ -19,10 +19,7 @@
636 #pragma once
637
638 #include <unity/storage/qt/Item.h>
639-
640-#include <QString>
641-
642-#include <memory>
643+#include <unity/storage/internal/AccountDetails.h>
644
645 class ProviderInterface;
646
647@@ -50,6 +47,8 @@
648 QString busName() const;
649 QString objectPath() const;
650 QString displayName() const;
651+ QString providerName() const;
652+ QString iconName() const;
653
654 ItemListJob* roots(QStringList const& keys) const;
655 ItemJob* get(QString const& itemId, QStringList const& keys) const;
656@@ -67,26 +66,14 @@
657 std::shared_ptr<ProviderInterface> provider() const;
658
659 static Account make_account(std::shared_ptr<RuntimeImpl> const& runtime_impl,
660- QString const& bus_name,
661- QString const& object_path,
662- QString const& id,
663- QString const& service_id,
664- QString const& display_name);
665+ storage::internal::AccountDetails const& details);
666
667 private:
668 AccountImpl(std::shared_ptr<RuntimeImpl> const& runtime_impl,
669- QString const& bus_name,
670- QString const& object_path,
671- QString const& id,
672- QString const& service_id,
673- QString const& display_name);
674+ storage::internal::AccountDetails const& details);
675
676 bool is_valid_;
677- QString bus_name_;
678- QString object_path_;
679- QString id_;
680- QString service_id_;
681- QString display_name_;
682+ storage::internal::AccountDetails details_;
683 std::weak_ptr<RuntimeImpl> runtime_impl_;
684 std::shared_ptr<ProviderInterface> provider_;
685
686
687=== modified file 'include/unity/storage/qt/internal/AccountsJobImpl.h'
688--- include/unity/storage/qt/internal/AccountsJobImpl.h 2016-11-02 02:54:48 +0000
689+++ include/unity/storage/qt/internal/AccountsJobImpl.h 2016-12-12 02:53:43 +0000
690@@ -18,9 +18,14 @@
691
692 #pragma once
693
694+#include <unity/storage/internal/AccountDetails.h>
695 #include <unity/storage/qt/AccountsJob.h>
696
697-#include <QTimer>
698+#pragma GCC diagnostic push
699+#pragma GCC diagnostic ignored "-Wcast-align"
700+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
701+#include <QDBusPendingReply>
702+#pragma GCC diagnostic pop
703
704 namespace unity
705 {
706@@ -31,12 +36,16 @@
707 namespace internal
708 {
709
710+class RuntimeImpl;
711+
712 class AccountsJobImpl : public QObject
713 {
714 Q_OBJECT
715 public:
716- AccountsJobImpl(AccountsJob* public_instance, std::shared_ptr<RuntimeImpl> const& runtime_impl);
717- AccountsJobImpl(AccountsJob* public_instance, StorageError const& error);
718+ AccountsJobImpl(std::shared_ptr<RuntimeImpl> const& runtime_impl,
719+ QString const& method,
720+ QDBusPendingReply<QList<storage::internal::AccountDetails>>& reply);
721+ AccountsJobImpl(StorageError const& error);
722 virtual ~AccountsJobImpl() = default;
723
724 bool isValid() const;
725@@ -45,21 +54,20 @@
726 QList<Account> accounts() const;
727 QVariantList accountsAsVariantList() const;
728
729-private Q_SLOTS:
730- void manager_ready();
731- void timeout();
732+ static AccountsJob* make_job(std::shared_ptr<RuntimeImpl> const& runtime_impl,
733+ QString const& method,
734+ QDBusPendingReply<QList<storage::internal::AccountDetails>>& reply);
735+ static AccountsJob* make_job(StorageError const& e);
736
737 private:
738 std::shared_ptr<RuntimeImpl> get_runtime_impl(QString const& method) const;
739- void initialize_accounts();
740 AccountsJob::Status emit_status_changed(AccountsJob::Status new_status) const;
741
742- AccountsJob* const public_instance_;
743+ AccountsJob* public_instance_;
744 AccountsJob::Status status_;
745 StorageError error_;
746- QList<unity::storage::qt::Account> accounts_;
747 std::weak_ptr<RuntimeImpl> const runtime_impl_;
748- QTimer timer_;
749+ QList<Account> accounts_;
750
751 friend class unity::storage::qt::AccountsJob;
752 };
753
754=== modified file 'include/unity/storage/qt/internal/Handler.h'
755--- include/unity/storage/qt/internal/Handler.h 2016-11-04 04:13:45 +0000
756+++ include/unity/storage/qt/internal/Handler.h 2016-12-12 02:53:43 +0000
757@@ -71,7 +71,7 @@
758 case StorageError::Type::NoError:
759 {
760 // LCOV_EXCL_START
761- QString msg = "impossible provider exception: " + e.errorString();
762+ QString msg = "impossible service exception: " + e.errorString();
763 qCritical().noquote() << msg;
764 e = StorageErrorImpl::local_comms_error(msg);
765 break;
766@@ -82,7 +82,7 @@
767 case StorageError::Type::ResourceError:
768 {
769 // Log these errors because they are unexpected.
770- QString msg = "provider exception: " + e.errorString();
771+ QString msg = "service exception: " + e.errorString();
772 qCritical().noquote() << msg;
773 break;
774 }
775
776=== modified file 'include/unity/storage/qt/internal/RuntimeImpl.h'
777--- include/unity/storage/qt/internal/RuntimeImpl.h 2016-09-22 01:52:20 +0000
778+++ include/unity/storage/qt/internal/RuntimeImpl.h 2016-12-12 02:53:43 +0000
779@@ -24,10 +24,11 @@
780 #pragma GCC diagnostic push
781 #pragma GCC diagnostic ignored "-Wcast-align"
782 #pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
783-#include <OnlineAccounts/Manager>
784 #include <QDBusConnection>
785 #pragma GCC diagnostic pop
786
787+class RegistryInterface;
788+
789 namespace unity
790 {
791 namespace storage
792@@ -45,7 +46,7 @@
793 {
794 public:
795 RuntimeImpl();
796- RuntimeImpl(QDBusConnection const& bus);
797+ RuntimeImpl(QDBusConnection const& conn);
798 RuntimeImpl(RuntimeImpl const&) = delete;
799 RuntimeImpl(RuntimeImpl&&) = delete;
800 ~RuntimeImpl();
801@@ -58,19 +59,17 @@
802 AccountsJob* accounts() const;
803 StorageError shutdown();
804
805- std::shared_ptr<OnlineAccounts::Manager> accounts_manager() const;
806-
807 Account make_test_account(QString const& bus_name,
808 QString const& object_path,
809- QString const& owner_id,
810- QString const& owner,
811- QString const& description);
812+ quint32 id,
813+ QString const& service_id,
814+ QString const& display_name);
815
816 private:
817 bool is_valid_;
818 StorageError error_;
819 QDBusConnection conn_;
820- std::shared_ptr<OnlineAccounts::Manager> accounts_manager_;
821+ std::unique_ptr<RegistryInterface> registry_;
822
823 friend class unity::storage::qt::Runtime;
824 };
825
826=== added directory 'include/unity/storage/registry'
827=== added file 'include/unity/storage/registry/Registry.h'
828--- include/unity/storage/registry/Registry.h 1970-01-01 00:00:00 +0000
829+++ include/unity/storage/registry/Registry.h 2016-12-12 02:53:43 +0000
830@@ -0,0 +1,35 @@
831+/*
832+ * Copyright (C) 2016 Canonical Ltd
833+ *
834+ * This program is free software: you can redistribute it and/or modify
835+ * it under the terms of the GNU Lesser General Public License version 3 as
836+ * published by the Free Software Foundation.
837+ *
838+ * This program is distributed in the hope that it will be useful,
839+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
840+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
841+ * GNU Lesser General Public License for more details.
842+ *
843+ * You should have received a copy of the GNU Lesser General Public License
844+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
845+ *
846+ * Authors: Michi Henning <michi.henning@canonical.com>
847+ */
848+
849+#pragma once
850+
851+#include <QString>
852+
853+namespace unity
854+{
855+namespace storage
856+{
857+namespace registry
858+{
859+
860+static QString const BUS_NAME(QStringLiteral("com.canonical.StorageFramework.Registry"));
861+static QString const OBJECT_PATH(QStringLiteral("/com/canonical/StorageFramework/Registry"));
862+
863+} // namespace registry
864+} // namespace storage
865+} // namespace unity
866
867=== added directory 'include/unity/storage/registry/internal'
868=== added file 'include/unity/storage/registry/internal/ListAccountsHandler.h'
869--- include/unity/storage/registry/internal/ListAccountsHandler.h 1970-01-01 00:00:00 +0000
870+++ include/unity/storage/registry/internal/ListAccountsHandler.h 2016-12-12 02:53:43 +0000
871@@ -0,0 +1,70 @@
872+/*
873+ * Copyright (C) 2016 Canonical Ltd
874+ *
875+ * This program is free software: you can redistribute it and/or modify
876+ * it under the terms of the GNU Lesser General Public License version 3 as
877+ * published by the Free Software Foundation.
878+ *
879+ * This program is distributed in the hope that it will be useful,
880+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
881+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
882+ * GNU Lesser General Public License for more details.
883+ *
884+ * You should have received a copy of the GNU Lesser General Public License
885+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
886+ *
887+ * Authors: Michi Henning <michi.henning@canonical.com>
888+ */
889+
890+#pragma once
891+
892+#include <unity/storage/internal/ActivityNotifier.h>
893+
894+#pragma GCC diagnostic push
895+#pragma GCC diagnostic ignored "-Wcast-align"
896+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
897+#include <OnlineAccounts/Manager>
898+#include <QDBusConnection>
899+#include <QDBusMessage>
900+#include <QTimer>
901+#pragma GCC diagnostic pop
902+
903+namespace unity
904+{
905+namespace storage
906+{
907+namespace registry
908+{
909+namespace internal
910+{
911+
912+class ListAccountsHandler : public QObject
913+{
914+ Q_OBJECT
915+
916+public:
917+ ListAccountsHandler(QDBusConnection const& conn,
918+ QDBusMessage const& msg,
919+ std::shared_ptr<storage::internal::InactivityTimer> const& timer);
920+ ~ListAccountsHandler();
921+
922+private Q_SLOTS:
923+ void manager_ready();
924+ void timeout();
925+
926+private:
927+ void initialize_manager();
928+
929+ QDBusConnection const conn_;
930+ QDBusMessage const msg_;
931+ OnlineAccounts::Manager manager_;
932+ QTimer timer_;
933+ storage::internal::ActivityNotifier activity_notifier_; // RAII guard variable
934+
935+ Q_DISABLE_COPY(ListAccountsHandler)
936+};
937+
938+} // namespace internal
939+} // namespace registry
940+} // namespace storage
941+} // namespace unity
942
943=== added file 'include/unity/storage/registry/internal/RegistryAdaptor.h'
944--- include/unity/storage/registry/internal/RegistryAdaptor.h 1970-01-01 00:00:00 +0000
945+++ include/unity/storage/registry/internal/RegistryAdaptor.h 2016-12-12 02:53:43 +0000
946@@ -0,0 +1,71 @@
947+/*
948+ * Copyright (C) 2016 Canonical Ltd
949+ *
950+ * This program is free software: you can redistribute it and/or modify
951+ * it under the terms of the GNU Lesser General Public License version 3 as
952+ * published by the Free Software Foundation.
953+ *
954+ * This program is distributed in the hope that it will be useful,
955+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
956+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
957+ * GNU Lesser General Public License for more details.
958+ *
959+ * You should have received a copy of the GNU Lesser General Public License
960+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
961+ *
962+ * Authors: Michi Henning <michi.henning@canonical.com>
963+ */
964+
965+#pragma once
966+
967+#include <unity/storage/internal/AccountDetails.h>
968+
969+#pragma GCC diagnostic push
970+#pragma GCC diagnostic ignored "-Wcast-align"
971+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
972+#include <QDBusConnection>
973+#include <QDBusContext>
974+#pragma GCC diagnostic pop
975+
976+#include <memory>
977+
978+namespace unity
979+{
980+namespace storage
981+{
982+namespace internal
983+{
984+
985+class InactivityTimer;
986+
987+} // namespace internal
988+
989+namespace registry
990+{
991+namespace internal
992+{
993+
994+class RegistryAdaptor : public QObject, protected QDBusContext
995+{
996+ Q_OBJECT
997+
998+public:
999+ RegistryAdaptor(QDBusConnection const& conn,
1000+ std::shared_ptr<storage::internal::InactivityTimer> const& timer,
1001+ QObject* parent = nullptr);
1002+ ~RegistryAdaptor();
1003+
1004+public Q_SLOTS:
1005+ QList<unity::storage::internal::AccountDetails> ListAccounts();
1006+
1007+private:
1008+ QDBusConnection conn_;
1009+ std::shared_ptr<storage::internal::InactivityTimer> timer_;
1010+
1011+ Q_DISABLE_COPY(RegistryAdaptor)
1012+};
1013+
1014+} // namespace internal
1015+} // namespace registry
1016+} // namespace storage
1017+} // namespace unity
1018
1019=== added file 'include/unity/storage/registry/internal/qdbus-last-error-msg.h'
1020--- include/unity/storage/registry/internal/qdbus-last-error-msg.h 1970-01-01 00:00:00 +0000
1021+++ include/unity/storage/registry/internal/qdbus-last-error-msg.h 2016-12-12 02:53:43 +0000
1022@@ -0,0 +1,41 @@
1023+/*
1024+ * Copyright (C) 2016 Canonical Ltd
1025+ *
1026+ * This program is free software: you can redistribute it and/or modify
1027+ * it under the terms of the GNU Lesser General Public License version 3 as
1028+ * published by the Free Software Foundation.
1029+ *
1030+ * This program is distributed in the hope that it will be useful,
1031+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1032+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1033+ * GNU Lesser General Public License for more details.
1034+ *
1035+ * You should have received a copy of the GNU Lesser General Public License
1036+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1037+ *
1038+ * Authors: Michi Henning <michi.henning@canonical.com>
1039+ */
1040+
1041+#pragma once
1042+
1043+#pragma GCC diagnostic push
1044+#pragma GCC diagnostic ignored "-Wcast-align"
1045+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
1046+#include <QDBusConnection>
1047+#pragma GCC diagnostic pop
1048+
1049+namespace unity
1050+{
1051+namespace storage
1052+{
1053+namespace registry
1054+{
1055+namespace internal
1056+{
1057+
1058+QString last_error_msg(QDBusConnection const& conn);
1059+
1060+} // namespace internal
1061+} // namespace registry
1062+} // namespace storage
1063+} // namespace unity
1064
1065=== modified file 'src/CMakeLists.txt'
1066--- src/CMakeLists.txt 2016-07-06 00:59:42 +0000
1067+++ src/CMakeLists.txt 2016-12-12 02:53:43 +0000
1068@@ -1,3 +1,4 @@
1069 add_subdirectory(internal)
1070 add_subdirectory(provider)
1071 add_subdirectory(qt)
1072+add_subdirectory(registry)
1073
1074=== added file 'src/internal/AccountDetails.cpp'
1075--- src/internal/AccountDetails.cpp 1970-01-01 00:00:00 +0000
1076+++ src/internal/AccountDetails.cpp 2016-12-12 02:53:43 +0000
1077@@ -0,0 +1,108 @@
1078+/*
1079+ * Copyright (C) 2016 Canonical Ltd
1080+ *
1081+ * This program is free software: you can redistribute it and/or modify
1082+ * it under the terms of the GNU Lesser General Public License version 3 as
1083+ * published by the Free Software Foundation.
1084+ *
1085+ * This program is distributed in the hope that it will be useful,
1086+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1087+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1088+ * GNU Lesser General Public License for more details.
1089+ *
1090+ * You should have received a copy of the GNU Lesser General Public License
1091+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1092+ *
1093+ * Authors: Michi Henning <michi.henning@canonical.com>
1094+ */
1095+
1096+#include <unity/storage/internal/AccountDetails.h>
1097+
1098+using namespace unity::storage::internal;
1099+
1100+namespace unity
1101+{
1102+namespace storage
1103+{
1104+namespace internal
1105+{
1106+
1107+bool operator==(AccountDetails const& lhs, AccountDetails const& rhs)
1108+{
1109+ return lhs.id == rhs.id
1110+ && lhs.serviceId == rhs.serviceId
1111+ && lhs.displayName == rhs.displayName;
1112+}
1113+
1114+bool operator!=(AccountDetails const& lhs, AccountDetails const& rhs)
1115+{
1116+ return !(lhs == rhs);
1117+}
1118+
1119+bool operator<(AccountDetails const& lhs, AccountDetails const& rhs)
1120+{
1121+ if (lhs.id < rhs.id)
1122+ {
1123+ return true;
1124+ }
1125+ if (lhs.id > rhs.id)
1126+ {
1127+ return false;
1128+ }
1129+ if (lhs.serviceId < rhs.serviceId)
1130+ {
1131+ return true;
1132+ }
1133+ if (lhs.serviceId > rhs.serviceId)
1134+ {
1135+ return false;
1136+ }
1137+ return lhs.displayName < rhs.displayName;
1138+}
1139+
1140+bool operator<=(AccountDetails const& lhs, AccountDetails const& rhs)
1141+{
1142+ return lhs < rhs || lhs == rhs;
1143+}
1144+
1145+bool operator>(AccountDetails const& lhs, AccountDetails const& rhs)
1146+{
1147+ return !(lhs <= rhs);
1148+}
1149+
1150+bool operator>=(AccountDetails const& lhs, AccountDetails const& rhs)
1151+{
1152+ return !(lhs < rhs);
1153+}
1154+
1155+QDBusArgument& operator<<(QDBusArgument& argument, storage::internal::AccountDetails const& account)
1156+{
1157+ argument.beginStructure();
1158+ argument << account.busName;
1159+ argument << account.objectPath;
1160+ argument << account.id;
1161+ argument << account.serviceId;
1162+ argument << account.displayName;
1163+ argument << account.providerName;
1164+ argument << account.iconName;
1165+ argument.endStructure();
1166+ return argument;
1167+}
1168+
1169+QDBusArgument const& operator>>(QDBusArgument const& argument, storage::internal::AccountDetails& account)
1170+{
1171+ argument.beginStructure();
1172+ argument >> account.busName;
1173+ argument >> account.objectPath;
1174+ argument >> account.id;
1175+ argument >> account.serviceId;
1176+ argument >> account.displayName;
1177+ argument >> account.providerName;
1178+ argument >> account.iconName;
1179+ argument.endStructure();
1180+ return argument;
1181+}
1182+
1183+} // namespace internal
1184+} // namespace storage
1185+} // namespace unity
1186
1187=== modified file 'src/internal/CMakeLists.txt'
1188--- src/internal/CMakeLists.txt 2016-08-12 06:19:22 +0000
1189+++ src/internal/CMakeLists.txt 2016-12-12 02:53:43 +0000
1190@@ -1,10 +1,18 @@
1191 set(src
1192+ AccountDetails.cpp
1193 dbusmarshal.cpp
1194+ EnvVars.cpp
1195+ InactivityTimer.cpp
1196 safe_strerror.cpp
1197 TraceMessageHandler.cpp
1198+ ${CMAKE_SOURCE_DIR}/include/unity/storage/internal/InactivityTimer.h
1199 )
1200
1201+
1202 add_library(storage-framework-common-internal STATIC ${src})
1203+
1204+set_target_properties(storage-framework-common-internal PROPERTIES AUTOMOC TRUE)
1205+
1206 target_link_libraries(storage-framework-common-internal
1207 Qt5::DBus
1208 )
1209
1210=== added file 'src/internal/EnvVars.cpp'
1211--- src/internal/EnvVars.cpp 1970-01-01 00:00:00 +0000
1212+++ src/internal/EnvVars.cpp 2016-12-12 02:53:43 +0000
1213@@ -0,0 +1,81 @@
1214+/*
1215+ * Copyright (C) 2016 Canonical Ltd
1216+ *
1217+ * This program is free software: you can redistribute it and/or modify
1218+ * it under the terms of the GNU Lesser General Public License version 3 as
1219+ * published by the Free Software Foundation.
1220+ *
1221+ * This program is distributed in the hope that it will be useful,
1222+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1223+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1224+ * GNU Lesser General Public License for more details.
1225+ *
1226+ * You should have received a copy of the GNU Lesser General Public License
1227+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1228+ *
1229+ * Authors: Michi Henning <michi.henning@canonical.com>
1230+ */
1231+
1232+#include <unity/storage/internal/EnvVars.h>
1233+
1234+#include <cassert>
1235+#include <QDebug>
1236+
1237+#include <stdlib.h>
1238+
1239+using namespace std;
1240+
1241+namespace unity
1242+{
1243+namespace storage
1244+{
1245+namespace internal
1246+{
1247+
1248+int EnvVars::registry_timeout_ms()
1249+{
1250+ int const dflt_val = REGISTRY_IDLE_TIMEOUT_DFLT * 1000;
1251+
1252+ auto const val = get(REGISTRY_IDLE_TIMEOUT);
1253+ if (val.empty())
1254+ {
1255+ return dflt_val;
1256+ }
1257+ try
1258+ {
1259+ size_t pos;
1260+ auto int_val = stoi(val, &pos);
1261+ if (pos != val.size())
1262+ {
1263+ throw invalid_argument("unexpected trailing character(s)");
1264+ }
1265+ if (int_val < 0)
1266+ {
1267+ throw invalid_argument("value must be >= 0");
1268+ }
1269+ return int_val;
1270+ }
1271+ catch (std::exception const& e)
1272+ {
1273+ qWarning().noquote().nospace() << "Invalid setting of env var " << QString::fromStdString(REGISTRY_IDLE_TIMEOUT)
1274+ << " (\"" << QString::fromStdString(val) << "\"): " << e.what();
1275+ qWarning().nospace() << "Using default value of " << REGISTRY_IDLE_TIMEOUT_DFLT;
1276+ }
1277+ return dflt_val;
1278+}
1279+
1280+string EnvVars::get(char const* var_name)
1281+{
1282+ assert(var_name != nullptr);
1283+
1284+ auto p = getenv(var_name);
1285+ if (!p)
1286+ {
1287+ return string();
1288+ }
1289+ return string(p);
1290+}
1291+
1292+} // namespace internal
1293+} // namespace storage
1294+} // namespace unity
1295
1296=== added file 'src/internal/InactivityTimer.cpp'
1297--- src/internal/InactivityTimer.cpp 1970-01-01 00:00:00 +0000
1298+++ src/internal/InactivityTimer.cpp 2016-12-12 02:53:43 +0000
1299@@ -0,0 +1,82 @@
1300+/*
1301+ * Copyright (C) 2016 Canonical Ltd
1302+ *
1303+ * This program is free software: you can redistribute it and/or modify
1304+ * it under the terms of the GNU Lesser General Public License version 3 as
1305+ * published by the Free Software Foundation.
1306+ *
1307+ * This program is distributed in the hope that it will be useful,
1308+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1309+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1310+ * GNU Lesser General Public License for more details.
1311+ *
1312+ * You should have received a copy of the GNU Lesser General Public License
1313+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1314+ *
1315+ * Authors: Michi Henning <michi.henning@canonical.com>
1316+ */
1317+
1318+#include <unity/storage/internal/InactivityTimer.h>
1319+
1320+#include <QDebug>
1321+
1322+#include <cassert>
1323+
1324+namespace unity
1325+{
1326+namespace storage
1327+{
1328+namespace internal
1329+{
1330+
1331+InactivityTimer::InactivityTimer(int timeout_ms, std::function<void()> timeout_func)
1332+ : timeout_ms_(timeout_ms)
1333+ , timeout_func_(timeout_func)
1334+ , num_requests_(0)
1335+{
1336+ assert(timeout_ms_ >= 0);
1337+ assert(timeout_func);
1338+
1339+ connect(&timer_, &QTimer::timeout, this, &InactivityTimer::timeout);
1340+}
1341+
1342+InactivityTimer::~InactivityTimer() = default;
1343+
1344+void InactivityTimer::request_started()
1345+{
1346+ assert(num_requests_ >= 0);
1347+
1348+ if (num_requests_++ == 0)
1349+ {
1350+ timer_.stop();
1351+ }
1352+}
1353+
1354+void InactivityTimer::request_finished()
1355+{
1356+ assert(num_requests_ > 0);
1357+
1358+ if (--num_requests_ == 0)
1359+ {
1360+ timer_.start(timeout_ms_);
1361+ }
1362+}
1363+
1364+void InactivityTimer::timeout()
1365+{
1366+ timer_.stop();
1367+ disconnect(this);
1368+ try
1369+ {
1370+ timeout_func_();
1371+ }
1372+ catch (std::exception const& e)
1373+ {
1374+ auto msg = QString("InactivityTimer::timeout(): exception from timeout callback: ") + e.what();
1375+ qWarning().nospace() << msg;
1376+ }
1377+}
1378+
1379+} // namespace internal
1380+} // namespace storage
1381+} // namespace unity
1382
1383=== modified file 'src/internal/TraceMessageHandler.cpp'
1384--- src/internal/TraceMessageHandler.cpp 2016-08-12 06:19:22 +0000
1385+++ src/internal/TraceMessageHandler.cpp 2016-12-12 02:53:43 +0000
1386@@ -80,10 +80,27 @@
1387
1388 } // namespace
1389
1390+TraceMessageHandler::TraceMessageHandler()
1391+ : old_message_handler_(qInstallMessageHandler(trace_message_handler))
1392+{
1393+}
1394+
1395 TraceMessageHandler::TraceMessageHandler(string const& prog_name)
1396-{
1397- prefix = prog_name;
1398- old_message_handler_ = qInstallMessageHandler(trace_message_handler);
1399+ : TraceMessageHandler()
1400+{
1401+ prefix = prog_name;
1402+}
1403+
1404+TraceMessageHandler::TraceMessageHandler(QString const& prog_name)
1405+ : TraceMessageHandler()
1406+{
1407+ prefix = prog_name.toStdString();
1408+}
1409+
1410+TraceMessageHandler::TraceMessageHandler(char const* prog_name)
1411+ : TraceMessageHandler()
1412+{
1413+ prefix = prog_name;
1414 }
1415
1416 TraceMessageHandler::~TraceMessageHandler()
1417
1418=== modified file 'src/qt/Account.cpp'
1419--- src/qt/Account.cpp 2016-11-03 06:41:00 +0000
1420+++ src/qt/Account.cpp 2016-12-12 02:53:43 +0000
1421@@ -93,6 +93,16 @@
1422 return p_->displayName();
1423 }
1424
1425+QString Account::providerName() const
1426+{
1427+ return p_->providerName();
1428+}
1429+
1430+QString Account::iconName() const
1431+{
1432+ return p_->iconName();
1433+}
1434+
1435 ItemListJob* Account::roots(QStringList const& keys) const
1436 {
1437 return p_->roots(keys);
1438
1439=== modified file 'src/qt/AccountsJob.cpp'
1440--- src/qt/AccountsJob.cpp 2016-11-02 02:54:48 +0000
1441+++ src/qt/AccountsJob.cpp 2016-12-12 02:53:43 +0000
1442@@ -18,7 +18,6 @@
1443
1444 #include <unity/storage/qt/AccountsJob.h>
1445
1446-#include <unity/storage/qt/Account.h>
1447 #include <unity/storage/qt/internal/AccountsJobImpl.h>
1448
1449 #include <QVariant>
1450@@ -33,13 +32,8 @@
1451 namespace qt
1452 {
1453
1454-AccountsJob::AccountsJob(shared_ptr<internal::RuntimeImpl> const& runtime)
1455- : p_(new internal::AccountsJobImpl(this, runtime))
1456-{
1457-}
1458-
1459-AccountsJob::AccountsJob(StorageError const& error)
1460- : p_(new internal::AccountsJobImpl(this, error))
1461+AccountsJob::AccountsJob(unique_ptr<internal::AccountsJobImpl> accounts_job_impl)
1462+ : p_(move(accounts_job_impl))
1463 {
1464 }
1465
1466
1467=== modified file 'src/qt/CMakeLists.txt'
1468--- src/qt/CMakeLists.txt 2016-10-12 08:08:48 +0000
1469+++ src/qt/CMakeLists.txt 2016-12-12 02:53:43 +0000
1470@@ -4,11 +4,20 @@
1471 CLASSNAME ProviderInterface
1472 INCLUDE unity/storage/internal/dbusmarshal.h
1473 )
1474-
1475 qt5_add_dbus_interface(generated_files
1476 ${CMAKE_SOURCE_DIR}/data/provider.xml
1477 ProviderInterface
1478 )
1479+
1480+set_source_files_properties(${CMAKE_SOURCE_DIR}/data/registry.xml PROPERTIES
1481+ CLASSNAME RegistryInterface
1482+ INCLUDE unity/storage/internal/AccountDetails.h
1483+)
1484+qt5_add_dbus_interface(generated_files
1485+ ${CMAKE_SOURCE_DIR}/data/registry.xml
1486+ RegistryInterface
1487+)
1488+
1489 set_source_files_properties(${generated_files} dbusmarshal.cpp PROPERTIES
1490 COMPILE_FLAGS "-Wno-ctor-dtor-privacy -Wno-missing-field-initializers"
1491 GENERATED TRUE
1492@@ -71,7 +80,6 @@
1493 target_include_directories(storage-framework-qt-client-v2 PRIVATE
1494 ${Qt5DBus_INCLUDE_DIRS}
1495 ${Qt5Network_INCLUDE_DIRS}
1496- ${ONLINEACCOUNTS_DEPS_INCLUDE_DIRS}
1497 )
1498 set_target_properties(storage-framework-qt-client-v2 PROPERTIES
1499 AUTOMOC TRUE
1500@@ -85,7 +93,6 @@
1501 Qt5::Core
1502 Qt5::DBus
1503 Qt5::Network
1504- ${ONLINEACCOUNTS_DEPS_LDFLAGS}
1505 )
1506 install(
1507 TARGETS storage-framework-qt-client-v2
1508
1509=== modified file 'src/qt/Runtime.cpp'
1510--- src/qt/Runtime.cpp 2016-09-22 01:52:20 +0000
1511+++ src/qt/Runtime.cpp 2016-12-12 02:53:43 +0000
1512@@ -70,11 +70,11 @@
1513
1514 Account Runtime::make_test_account(QString const& bus_name,
1515 QString const& object_path,
1516- QString const& owner_id,
1517- QString const& owner,
1518- QString const& description) const
1519+ quint32 id,
1520+ QString const& service_id,
1521+ QString const& display_name) const
1522 {
1523- return p_->make_test_account(bus_name, object_path, owner_id, owner, description);
1524+ return p_->make_test_account(bus_name, object_path, id, service_id, display_name);
1525 }
1526
1527 } // namespace qt
1528
1529=== modified file 'src/qt/client/internal/remote_client/RuntimeImpl.cpp'
1530--- src/qt/client/internal/remote_client/RuntimeImpl.cpp 2016-11-02 09:32:53 +0000
1531+++ src/qt/client/internal/remote_client/RuntimeImpl.cpp 2016-12-12 02:53:43 +0000
1532@@ -47,7 +47,7 @@
1533
1534 static const map<QString, QString> BUS_NAMES =
1535 {
1536- { "google-drive-scope", "com.canonical.StorageFramework.Provider.ProviderTest" },
1537+ { "storage-provider-test", "com.canonical.StorageFramework.Provider.ProviderTest" },
1538 { "com.canonical.scopes.mcloud_mcloud_mcloud", "com.canonical.StorageFramework.Provider.McloudProvider" },
1539 { "storage-provider-owncloud", "com.canonical.StorageFramework.Provider.OwnCloud" },
1540 { "storage-provider-onedrive", "com.canonical.StorageFramework.Provider.OnedriveProvider" },
1541
1542=== modified file 'src/qt/internal/AccountImpl.cpp'
1543--- src/qt/internal/AccountImpl.cpp 2016-11-03 06:41:00 +0000
1544+++ src/qt/internal/AccountImpl.cpp 2016-12-12 02:53:43 +0000
1545@@ -48,37 +48,39 @@
1546 }
1547
1548 AccountImpl::AccountImpl(shared_ptr<RuntimeImpl> const& runtime_impl,
1549- QString const& bus_name,
1550- QString const& object_path,
1551- QString const& id,
1552- QString const& service_id,
1553- QString const& display_name)
1554+ storage::internal::AccountDetails const& details)
1555 : is_valid_(true)
1556- , bus_name_(bus_name)
1557- , object_path_(object_path)
1558- , id_(id)
1559- , service_id_(service_id)
1560- , display_name_(display_name)
1561+ , details_(details)
1562 , runtime_impl_(runtime_impl)
1563- , provider_(new ProviderInterface(bus_name, object_path, runtime_impl->connection()))
1564+ , provider_(new ProviderInterface(details.busName, details.objectPath.path(), runtime_impl->connection()))
1565 {
1566- assert(!bus_name.isEmpty());
1567- assert(!object_path.isEmpty());
1568+ assert(!details.busName.isEmpty());
1569+ assert(!details.objectPath.path().isEmpty());
1570 }
1571
1572 QString AccountImpl::busName() const
1573 {
1574- return is_valid_ ? bus_name_ : "";
1575+ return is_valid_ ? details_.busName : "";
1576 }
1577
1578 QString AccountImpl::objectPath() const
1579 {
1580- return is_valid_ ? object_path_ : "";
1581+ return is_valid_ ? details_.objectPath.path() : QDBusObjectPath().path();
1582 }
1583
1584 QString AccountImpl::displayName() const
1585 {
1586- return is_valid_ ? display_name_ : "";
1587+ return is_valid_ ? details_.displayName : "";
1588+}
1589+
1590+QString AccountImpl::providerName() const
1591+{
1592+ return is_valid_ ? details_.providerName : "";
1593+}
1594+
1595+QString AccountImpl::iconName() const
1596+{
1597+ return is_valid_ ? details_.iconName : "";
1598 }
1599
1600 ItemListJob* AccountImpl::roots(QStringList const& keys) const
1601@@ -101,7 +103,8 @@
1602 {
1603 if (md.type != ItemType::root)
1604 {
1605- QString msg = method + ": provider returned non-root item type: " + QString::number(int(md.type));
1606+ QString msg = method + ": provider returned non-root item type: " + QString::number(int(md.type)) +
1607+ " (id = " + md.item_id + ")";
1608 qCritical().noquote() << msg;
1609 throw StorageErrorImpl::local_comms_error(msg);
1610 }
1611@@ -141,10 +144,7 @@
1612 {
1613 if (is_valid_)
1614 {
1615- return other.is_valid_
1616- && id_ == other.id_
1617- && service_id_ == other.service_id_
1618- && display_name_ == other.display_name_;
1619+ return other.is_valid_ && details_ == other.details_;
1620 }
1621 return !other.is_valid_;
1622 }
1623@@ -164,24 +164,7 @@
1624 {
1625 return false;
1626 }
1627- assert(is_valid_ && other.is_valid_);
1628- if (id_ < other.id_)
1629- {
1630- return true;
1631- }
1632- if (id_ > other.id_)
1633- {
1634- return false;
1635- }
1636- if (service_id_ < other.service_id_)
1637- {
1638- return true;
1639- }
1640- if (service_id_ > other.service_id_)
1641- {
1642- return false;
1643- }
1644- return display_name_ < other.display_name_;
1645+ return details_ < other.details_;
1646 }
1647
1648 bool AccountImpl::operator<=(AccountImpl const& other) const
1649@@ -215,21 +198,16 @@
1650 {
1651 return 0;
1652 }
1653- size_t hash = 0;
1654- boost::hash_combine(hash, qHash(service_id_));
1655- boost::hash_combine(hash, qHash(id_));
1656- boost::hash_combine(hash, qHash(display_name_));
1657+ size_t hash = details_.id;
1658+ boost::hash_combine(hash, qHash(details_.serviceId));
1659+ boost::hash_combine(hash, qHash(details_.displayName));
1660 return hash;
1661 }
1662
1663 Account AccountImpl::make_account(shared_ptr<RuntimeImpl> const& runtime,
1664- QString const& bus_name,
1665- QString const& object_path,
1666- QString const& id,
1667- QString const& service_id,
1668- QString const& display_name)
1669+ storage::internal::AccountDetails const& details)
1670 {
1671- shared_ptr<AccountImpl> p(new AccountImpl(runtime, bus_name, object_path, id, service_id, display_name));
1672+ shared_ptr<AccountImpl> p(new AccountImpl(runtime, details));
1673 return Account(p);
1674 }
1675
1676
1677=== modified file 'src/qt/internal/AccountsJobImpl.cpp'
1678--- src/qt/internal/AccountsJobImpl.cpp 2016-11-03 07:33:40 +0000
1679+++ src/qt/internal/AccountsJobImpl.cpp 2016-12-12 02:53:43 +0000
1680@@ -18,12 +18,12 @@
1681
1682 #include <unity/storage/qt/internal/AccountsJobImpl.h>
1683
1684+#include "RegistryInterface.h"
1685 #include <unity/storage/qt/internal/AccountImpl.h>
1686+#include <unity/storage/qt/internal/Handler.h>
1687 #include <unity/storage/qt/internal/RuntimeImpl.h>
1688 #include <unity/storage/qt/internal/StorageErrorImpl.h>
1689
1690-#include <OnlineAccounts/Account>
1691-
1692 #include <cassert>
1693
1694 using namespace std;
1695@@ -37,38 +37,45 @@
1696 namespace internal
1697 {
1698
1699-namespace
1700-{
1701-
1702-// TODO: We retrieve the accounts directly from online accounts until we have a working registry.
1703-
1704-static map<QString, QString> const BUS_NAMES =
1705-{
1706- { "google-drive-scope", "com.canonical.StorageFramework.Provider.ProviderTest" },
1707- { "com.canonical.scopes.mcloud_mcloud_mcloud", "com.canonical.StorageFramework.Provider.McloudProvider" },
1708- { "storage-provider-owncloud", "com.canonical.StorageFramework.Provider.OwnCloud" },
1709- { "storage-provider-onedrive", "com.canonical.StorageFramework.Provider.OnedriveProvider" },
1710-};
1711-
1712-} // namespace
1713-
1714-AccountsJobImpl::AccountsJobImpl(AccountsJob* public_instance, shared_ptr<RuntimeImpl> const& runtime_impl)
1715- : public_instance_(public_instance)
1716- , status_(AccountsJob::Status::Loading)
1717+AccountsJobImpl::AccountsJobImpl(shared_ptr<RuntimeImpl> const& runtime_impl,
1718+ QString const& method,
1719+ QDBusPendingReply<QList<storage::internal::AccountDetails>>& reply)
1720+ : status_(AccountsJob::Status::Loading)
1721 , runtime_impl_(runtime_impl)
1722 {
1723- assert(public_instance);
1724 assert(runtime_impl);
1725
1726- initialize_accounts();
1727+ auto process_reply = [this, method](decltype(reply)& r)
1728+ {
1729+ auto runtime = get_runtime_impl(method);
1730+ if (!runtime || !runtime->isValid())
1731+ {
1732+ return;
1733+ }
1734+
1735+ for (auto const& ad : r.value())
1736+ {
1737+ auto a = AccountImpl::make_account(runtime, ad);
1738+ accounts_.append(a);
1739+ }
1740+ status_ = AccountsJob::Status::Finished;
1741+ Q_EMIT public_instance_->statusChanged(status_);
1742+ };
1743+
1744+ auto process_error = [this](StorageError const& error)
1745+ {
1746+ error_ = error;
1747+ status_ = AccountsJob::Status::Error;
1748+ Q_EMIT public_instance_->statusChanged(status_);
1749+ };
1750+
1751+ new Handler<QList<storage::internal::AccountDetails>>(this, reply, process_reply, process_error);
1752 }
1753
1754-AccountsJobImpl::AccountsJobImpl(AccountsJob* public_instance, StorageError const& error)
1755- : public_instance_(public_instance)
1756- , status_(AccountsJob::Status::Loading)
1757+AccountsJobImpl::AccountsJobImpl(StorageError const& error)
1758+ : status_(AccountsJob::Status::Error)
1759 , error_(error)
1760 {
1761- assert(public_instance);
1762 assert(error.type() != StorageError::Type::NoError);
1763
1764 status_ = emit_status_changed(AccountsJob::Status::Error);
1765@@ -113,21 +120,27 @@
1766 return account_list;
1767 }
1768
1769-void AccountsJobImpl::manager_ready()
1770+AccountsJob* AccountsJobImpl::make_job(shared_ptr<RuntimeImpl> const& runtime,
1771+ QString const& method,
1772+ QDBusPendingReply<QList<storage::internal::AccountDetails>>& reply)
1773 {
1774- timer_.stop();
1775- disconnect(this);
1776- initialize_accounts();
1777+ unique_ptr<AccountsJobImpl> impl(new AccountsJobImpl(runtime, method, reply));
1778+ auto job = new AccountsJob(move(impl));
1779+ job->p_->public_instance_ = job;
1780+ return job;
1781 }
1782
1783-// LCOV_EXCL_START
1784-void AccountsJobImpl::timeout()
1785+AccountsJob* AccountsJobImpl::make_job(StorageError const& error)
1786 {
1787- disconnect(this);
1788- error_ = StorageErrorImpl::local_comms_error("AccountsJob(): timeout retrieving Online accounts");
1789- status_ = emit_status_changed(AccountsJob::Status::Error);
1790+ unique_ptr<AccountsJobImpl> impl(new AccountsJobImpl(error));
1791+ auto job = new AccountsJob(move(impl));
1792+ job->p_->public_instance_ = job;
1793+ QMetaObject::invokeMethod(job,
1794+ "statusChanged",
1795+ Qt::QueuedConnection,
1796+ Q_ARG(unity::storage::qt::AccountsJob::Status, job->p_->status_));
1797+ return job;
1798 }
1799-// LCOV_EXCL_STOP
1800
1801 AccountsJob::Status AccountsJobImpl::emit_status_changed(AccountsJob::Status new_status) const
1802 {
1803@@ -152,43 +165,11 @@
1804 auto This = const_cast<AccountsJobImpl*>(this);
1805 This->error_ = StorageErrorImpl::runtime_destroyed_error(msg);
1806 This->status_ = emit_status_changed(AccountsJob::Status::Error);
1807+ return nullptr;
1808 }
1809 return runtime;
1810 }
1811
1812-void AccountsJobImpl::initialize_accounts()
1813-{
1814- auto runtime = get_runtime_impl("AccountsJob()");
1815- assert(runtime);
1816-
1817- auto manager = runtime->accounts_manager();
1818- if (!manager->isReady())
1819- {
1820- connect(manager.get(), &OnlineAccounts::Manager::ready, this, &AccountsJobImpl::manager_ready);
1821- connect(&timer_, &QTimer::timeout, this, &AccountsJobImpl::timeout);
1822- timer_.setSingleShot(true);
1823- timer_.start(30000); // TODO: Need config for this eventually.
1824- return;
1825- }
1826-
1827- for (auto const map_entry : BUS_NAMES)
1828- {
1829- auto service_id = map_entry.first;
1830- for (auto const& a : manager->availableAccounts(service_id))
1831- {
1832- auto object_path = QStringLiteral("/provider/%1").arg(a->id());
1833- auto bus_name = map_entry.second;
1834- accounts_.append(AccountImpl::make_account(runtime,
1835- bus_name,
1836- object_path,
1837- QString::number(a->id()),
1838- a->serviceId(),
1839- a->displayName()));
1840- }
1841- }
1842- status_ = emit_status_changed(AccountsJob::Status::Finished);
1843-}
1844-
1845 } // namespace internal
1846 } // namespace qt
1847 } // namespace storage
1848
1849=== modified file 'src/qt/internal/ItemImpl.cpp'
1850--- src/qt/internal/ItemImpl.cpp 2016-11-03 03:41:24 +0000
1851+++ src/qt/internal/ItemImpl.cpp 2016-12-12 02:53:43 +0000
1852@@ -153,7 +153,7 @@
1853 {
1854 if (md.type == ItemType::file)
1855 {
1856- QString msg = method + ": provider returned a file as a parent";
1857+ QString msg = method + ": provider returned a file as a parent (id = " + md.item_id + ")";
1858 qCritical().noquote() << msg;
1859 throw StorageErrorImpl::local_comms_error(msg);
1860 }
1861@@ -178,7 +178,8 @@
1862 ||
1863 (md_.type != ItemType::file && md.type == ItemType::file))
1864 {
1865- QString msg = method + ": source and target item type differ";
1866+ QString msg = method + "provider error: source and target item type differ (source id = " +
1867+ md_.item_id + ", target id = " + md.item_id + ")";
1868 qCritical().noquote() << msg;
1869 throw StorageErrorImpl::local_comms_error(msg);
1870 }
1871@@ -203,7 +204,7 @@
1872 {
1873 if (md.type == ItemType::root)
1874 {
1875- QString msg = method + ": impossible root item returned by provider";
1876+ QString msg = method + ": impossible root item returned by provider (id = " + md.item_id + ")";
1877 qCritical().noquote() << msg;
1878 throw StorageErrorImpl::local_comms_error(msg);
1879 }
1880@@ -211,7 +212,8 @@
1881 ||
1882 (md_.type != ItemType::file && md.type == ItemType::file))
1883 {
1884- QString msg = method + ": provider error: source and target item type differ";
1885+ QString msg = method + ": provider error: source and target item type differ (source id = " +
1886+ md_.item_id + ", target id = " + md.item_id + ")";
1887 qCritical().noquote() << msg;
1888 throw StorageErrorImpl::local_comms_error(msg);
1889 }
1890@@ -266,7 +268,7 @@
1891 {
1892 if (md.type != storage::ItemType::file)
1893 {
1894- QString msg = method + ": impossible folder item returned by provider";
1895+ QString msg = method + ": impossible folder item returned by provider (id = " + md.item_id + ")";
1896 qCritical().noquote() << msg;
1897 throw StorageErrorImpl::local_comms_error(msg);
1898 }
1899@@ -318,7 +320,7 @@
1900 {
1901 if (md.type == storage::ItemType::root)
1902 {
1903- QString msg = method + ": impossible root item returned by provider";
1904+ QString msg = method + ": impossible root item returned by provider (id = " + md.item_id + ")";
1905 qCritical().noquote() << msg;
1906 throw StorageErrorImpl::local_comms_error(msg);
1907 }
1908@@ -379,7 +381,7 @@
1909 {
1910 return;
1911 }
1912- QString msg = method + ": impossible file item returned by provider";
1913+ QString msg = method + ": impossible file item returned by provider (id = " + md.item_id + ")";
1914 qCritical().noquote() << msg;
1915 throw StorageErrorImpl::local_comms_error(msg);
1916 };
1917@@ -423,7 +425,7 @@
1918 {
1919 if (md.type != storage::ItemType::file)
1920 {
1921- QString msg = method + ": impossible folder item returned by provider";
1922+ QString msg = method + ": impossible folder item returned by provider (id = " + md.item_id + ")";
1923 qCritical().noquote() << msg;
1924 throw StorageErrorImpl::local_comms_error(msg);
1925 }
1926
1927=== modified file 'src/qt/internal/ItemListJobImpl.cpp'
1928--- src/qt/internal/ItemListJobImpl.cpp 2016-10-12 07:23:15 +0000
1929+++ src/qt/internal/ItemListJobImpl.cpp 2016-12-12 02:53:43 +0000
1930@@ -62,16 +62,14 @@
1931 auto item = ItemImpl::make_item(method_, md, account_impl_);
1932 items.append(item);
1933 }
1934- catch (StorageError const&)
1935+ catch (StorageError const& e)
1936 {
1937 // Bad metadata received from provider, validate_() or make_item() have logged it.
1938+ error_ = e;
1939 }
1940 }
1941- status_ = ItemListJob::Status::Finished;
1942- if (!items.isEmpty())
1943- {
1944- Q_EMIT public_instance_->itemsReady(items);
1945- }
1946+ status_ = error_.type() == StorageError::NoError ? ItemListJob::Finished : ItemListJob::Error;
1947+ Q_EMIT public_instance_->itemsReady(items);
1948 Q_EMIT public_instance_->statusChanged(status_);
1949 };
1950
1951
1952=== modified file 'src/qt/internal/MultiItemListJobImpl.cpp'
1953--- src/qt/internal/MultiItemListJobImpl.cpp 2016-10-12 07:23:15 +0000
1954+++ src/qt/internal/MultiItemListJobImpl.cpp 2016-12-12 02:53:43 +0000
1955@@ -86,10 +86,7 @@
1956 {
1957 status_ = ItemListJob::Status::Finished;
1958 }
1959- if (!items.isEmpty())
1960- {
1961- Q_EMIT public_instance_->itemsReady(items);
1962- }
1963+ Q_EMIT public_instance_->itemsReady(items);
1964 if (token.isEmpty())
1965 {
1966 Q_EMIT public_instance_->statusChanged(status_);
1967
1968=== modified file 'src/qt/internal/RuntimeImpl.cpp'
1969--- src/qt/internal/RuntimeImpl.cpp 2016-10-10 05:24:16 +0000
1970+++ src/qt/internal/RuntimeImpl.cpp 2016-12-12 02:53:43 +0000
1971@@ -18,15 +18,17 @@
1972
1973 #include <unity/storage/qt/internal/RuntimeImpl.h>
1974
1975+#include "RegistryInterface.h"
1976 #include <unity/storage/internal/dbusmarshal.h>
1977-#include <unity/storage/qt/AccountsJob.h>
1978+#include <unity/storage/internal/EnvVars.h>
1979 #include <unity/storage/qt/internal/AccountImpl.h>
1980+#include <unity/storage/qt/internal/AccountsJobImpl.h>
1981 #include <unity/storage/qt/internal/StorageErrorImpl.h>
1982-#include <unity/storage/qt/Item.h>
1983 #include <unity/storage/qt/ItemJob.h>
1984 #include <unity/storage/qt/ItemListJob.h>
1985 #include <unity/storage/qt/Runtime.h>
1986 #include <unity/storage/qt/VoidJob.h>
1987+#include <unity/storage/registry/Registry.h>
1988
1989 #include <QDBusError>
1990 #include <QDBusMetaType>
1991@@ -57,6 +59,9 @@
1992
1993 qDBusRegisterMetaType<unity::storage::internal::ItemMetadata>();
1994 qDBusRegisterMetaType<QList<unity::storage::internal::ItemMetadata>>();
1995+
1996+ qDBusRegisterMetaType<unity::storage::internal::AccountDetails>();
1997+ qDBusRegisterMetaType<QList<unity::storage::internal::AccountDetails>>();
1998 }
1999
2000 }
2001@@ -66,10 +71,12 @@
2002 {
2003 }
2004
2005-RuntimeImpl::RuntimeImpl(QDBusConnection const& bus)
2006+RuntimeImpl::RuntimeImpl(QDBusConnection const& conn)
2007 : is_valid_(true)
2008- , conn_(bus)
2009- , accounts_manager_(new OnlineAccounts::Manager("", conn_))
2010+ , conn_(conn)
2011+ , registry_(new RegistryInterface(storage::registry::BUS_NAME,
2012+ storage::registry::OBJECT_PATH,
2013+ conn_))
2014 {
2015 register_meta_types();
2016 }
2017@@ -96,13 +103,17 @@
2018
2019 AccountsJob* RuntimeImpl::accounts() const
2020 {
2021+ QString const method = "Runtime::accounts()";
2022+
2023 if (!is_valid_)
2024 {
2025 QString msg = "Runtime::accounts(): Runtime was destroyed previously";
2026- return new AccountsJob(StorageErrorImpl::runtime_destroyed_error(msg));
2027+ return AccountsJobImpl::make_job(StorageErrorImpl::runtime_destroyed_error(msg));
2028 }
2029- auto This = const_cast<RuntimeImpl*>(this);
2030- return new AccountsJob(This->shared_from_this());
2031+
2032+ auto reply = registry_->ListAccounts();
2033+ auto This = const_pointer_cast<RuntimeImpl>(shared_from_this());
2034+ return AccountsJobImpl::make_job(This, method, reply);
2035 }
2036
2037 StorageError RuntimeImpl::shutdown()
2038@@ -116,23 +127,14 @@
2039 return error_;
2040 }
2041
2042-shared_ptr<OnlineAccounts::Manager> RuntimeImpl::accounts_manager() const
2043-{
2044- return accounts_manager_;
2045-}
2046-
2047 Account RuntimeImpl::make_test_account(QString const& bus_name,
2048 QString const& object_path,
2049- QString const& owner_id,
2050- QString const& owner,
2051- QString const& description)
2052+ quint32 id,
2053+ QString const& service_id,
2054+ QString const& name)
2055 {
2056- return AccountImpl::make_account(shared_from_this(),
2057- bus_name,
2058- object_path,
2059- owner_id,
2060- owner,
2061- description);
2062+ storage::internal::AccountDetails ad{bus_name, QDBusObjectPath(object_path), id, service_id, name, "", ""};
2063+ return AccountImpl::make_account(shared_from_this(), ad);
2064 }
2065
2066 } // namespace internal
2067
2068=== modified file 'src/qt/internal/validate.cpp'
2069--- src/qt/internal/validate.cpp 2016-11-02 06:06:32 +0000
2070+++ src/qt/internal/validate.cpp 2016-12-12 02:53:43 +0000
2071@@ -110,69 +110,81 @@
2072 {
2073 using namespace unity::storage::metadata;
2074
2075- QString prefix = method + ": received invalid metadata from provider: ";
2076-
2077- // Basic sanity checks for mandatory fields.
2078- if (md.item_id.isEmpty())
2079- {
2080- throw StorageErrorImpl::local_comms_error(prefix + "item_id cannot be empty");
2081- }
2082- if (md.type != ItemType::root)
2083- {
2084- if (md.parent_ids.isEmpty())
2085- {
2086- throw StorageErrorImpl::local_comms_error(prefix + "file or folder must have at least one parent ID");
2087- }
2088- for (int i = 0; i < md.parent_ids.size(); ++i)
2089- {
2090- if (md.parent_ids.at(i).isEmpty())
2091- {
2092- throw StorageErrorImpl::local_comms_error(prefix + "parent_id of file or folder cannot be empty");
2093- }
2094- }
2095- }
2096- if (md.type == ItemType::root && !md.parent_ids.isEmpty())
2097- {
2098- throw StorageErrorImpl::local_comms_error(prefix + "parent_ids of root must be empty");
2099- }
2100- if (md.type != ItemType::root) // Dropbox does not support metadata for roots.
2101- {
2102- if (md.name.isEmpty())
2103- {
2104- throw StorageErrorImpl::local_comms_error(prefix + "name cannot be empty");
2105- }
2106- }
2107- if (md.type == ItemType::file && md.etag.isEmpty()) // WebDav doesn't do etag for folders.
2108- {
2109- throw StorageErrorImpl::local_comms_error(prefix + "etag of a file cannot be empty");
2110- }
2111-
2112- // Sanity check metadata to make sure only known metadata keys appear.
2113- QMapIterator<QString, QVariant> actual(md.metadata);
2114- while (actual.hasNext())
2115- {
2116- actual.next();
2117- auto known = known_metadata.find(actual.key().toStdString());
2118- if (known == known_metadata.end())
2119- {
2120- qWarning().noquote().nospace() << prefix << "unknown metadata key: \"" << actual.key() << "\"";
2121- }
2122- else
2123- {
2124- validate_type_and_value(prefix, actual, known);
2125- }
2126- }
2127-
2128- // Sanity check metadata to make sure that mandatory fields are present.
2129- if (md.type == ItemType::file)
2130- {
2131- if (!md.metadata.contains(metadata::SIZE_IN_BYTES) ||
2132- !md.metadata.contains(metadata::LAST_MODIFIED_TIME))
2133- {
2134- QString msg = prefix + "missing key \"" + metadata::SIZE_IN_BYTES + "\" "
2135- "in metadata for \"" + md.item_id + "\"";
2136- throw StorageErrorImpl::local_comms_error(msg);
2137- }
2138+ QString prefix = method + ": received invalid metadata from provider";
2139+ if (!md.item_id.isEmpty())
2140+ {
2141+ prefix += " (id = " + md.item_id + ")";
2142+ }
2143+ prefix += ": ";
2144+
2145+ try
2146+ {
2147+ // Basic sanity checks for mandatory fields.
2148+ if (md.item_id.isEmpty())
2149+ {
2150+ throw StorageErrorImpl::local_comms_error(prefix + "item_id cannot be empty");
2151+ }
2152+ if (md.type != ItemType::root)
2153+ {
2154+ if (md.parent_ids.isEmpty())
2155+ {
2156+ throw StorageErrorImpl::local_comms_error(prefix + "file or folder must have at least one parent ID");
2157+ }
2158+ for (int i = 0; i < md.parent_ids.size(); ++i)
2159+ {
2160+ if (md.parent_ids.at(i).isEmpty())
2161+ {
2162+ throw StorageErrorImpl::local_comms_error(prefix + "parent_id of file or folder cannot be empty");
2163+ }
2164+ }
2165+ }
2166+ if (md.type == ItemType::root && !md.parent_ids.isEmpty())
2167+ {
2168+ throw StorageErrorImpl::local_comms_error(prefix + "parent_ids of root must be empty");
2169+ }
2170+ if (md.type != ItemType::root) // Dropbox does not support metadata for roots.
2171+ {
2172+ if (md.name.isEmpty())
2173+ {
2174+ throw StorageErrorImpl::local_comms_error(prefix + "name cannot be empty");
2175+ }
2176+ }
2177+ if (md.type == ItemType::file && md.etag.isEmpty()) // WebDav doesn't do etag for folders.
2178+ {
2179+ throw StorageErrorImpl::local_comms_error(prefix + "etag of a file cannot be empty");
2180+ }
2181+
2182+ // Sanity check metadata to make sure only known metadata keys appear.
2183+ QMapIterator<QString, QVariant> actual(md.metadata);
2184+ while (actual.hasNext())
2185+ {
2186+ actual.next();
2187+ auto known = known_metadata.find(actual.key().toStdString());
2188+ if (known == known_metadata.end())
2189+ {
2190+ qWarning().noquote().nospace() << prefix << "unknown metadata key: \"" << actual.key() << "\"";
2191+ }
2192+ else
2193+ {
2194+ validate_type_and_value(prefix, actual, known);
2195+ }
2196+ }
2197+
2198+ // Sanity check metadata to make sure that mandatory fields are present.
2199+ if (md.type == ItemType::file)
2200+ {
2201+ if (!md.metadata.contains(metadata::SIZE_IN_BYTES) ||
2202+ !md.metadata.contains(metadata::LAST_MODIFIED_TIME))
2203+ {
2204+ QString msg = prefix + "missing key \"" + metadata::SIZE_IN_BYTES + "\" in metadata";
2205+ throw StorageErrorImpl::local_comms_error(msg);
2206+ }
2207+ }
2208+ }
2209+ catch (StorageError const& e)
2210+ {
2211+ qCritical().noquote() << e.errorString();
2212+ throw;
2213 }
2214 }
2215
2216
2217=== added directory 'src/registry'
2218=== added file 'src/registry/CMakeLists.txt'
2219--- src/registry/CMakeLists.txt 1970-01-01 00:00:00 +0000
2220+++ src/registry/CMakeLists.txt 2016-12-12 02:53:43 +0000
2221@@ -0,0 +1,47 @@
2222+include_directories(
2223+ ${CMAKE_CURRENT_BINARY_DIR}
2224+ ${ONLINEACCOUNTS_DEPS_INCLUDE_DIRS}
2225+)
2226+
2227+set(TARGET "storage-framework-registry")
2228+
2229+qt5_add_dbus_adaptor(adaptor_files
2230+ ${CMAKE_SOURCE_DIR}/data/registry.xml
2231+ unity/storage/registry/internal/RegistryAdaptor.h
2232+ unity::storage::registry::internal::RegistryAdaptor
2233+)
2234+
2235+set_source_files_properties(${adaptor_files} PROPERTIES
2236+ COMPILE_FLAGS "-Wno-ctor-dtor-privacy -Wno-missing-field-initializers"
2237+ GENERATED TRUE
2238+)
2239+
2240+add_executable(${TARGET}
2241+ internal/ListAccountsHandler.cpp
2242+ internal/qdbus-last-error-msg.cpp
2243+ internal/RegistryAdaptor.cpp
2244+ main.cpp
2245+ ${CMAKE_SOURCE_DIR}/include/unity/storage/registry/internal/ListAccountsHandler.h
2246+ ${CMAKE_SOURCE_DIR}/include/unity/storage/registry/internal/RegistryAdaptor.h
2247+ ${adaptor_files})
2248+
2249+set_target_properties(${TARGET} PROPERTIES AUTOMOC TRUE)
2250+
2251+target_link_libraries(${TARGET}
2252+ storage-framework-common-internal
2253+ Qt5::Core
2254+ Qt5::DBus
2255+ ${ONLINEACCOUNTS_DEPS_LDFLAGS}
2256+)
2257+
2258+install(
2259+ TARGETS ${TARGET}
2260+ RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}/${PROJECT_NAME}
2261+)
2262+
2263+configure_file(com.canonical.StorageFramework.Registry.service.in com.canonical.StorageFramework.Registry.service)
2264+
2265+install(
2266+ FILES ${CMAKE_CURRENT_BINARY_DIR}/com.canonical.StorageFramework.Registry.service
2267+ DESTINATION ${CMAKE_INSTALL_DATADIR}/dbus-1/services
2268+)
2269
2270=== added file 'src/registry/com.canonical.StorageFramework.Registry.service.in'
2271--- src/registry/com.canonical.StorageFramework.Registry.service.in 1970-01-01 00:00:00 +0000
2272+++ src/registry/com.canonical.StorageFramework.Registry.service.in 2016-12-12 02:53:43 +0000
2273@@ -0,0 +1,3 @@
2274+[D-BUS Service]
2275+Name=com.canonical.StorageFramework.Registry
2276+Exec=@CMAKE_INSTALL_FULL_LIBDIR@/@PROJECT_NAME@/storage-framework-registry
2277
2278=== added directory 'src/registry/internal'
2279=== added file 'src/registry/internal/ListAccountsHandler.cpp'
2280--- src/registry/internal/ListAccountsHandler.cpp 1970-01-01 00:00:00 +0000
2281+++ src/registry/internal/ListAccountsHandler.cpp 2016-12-12 02:53:43 +0000
2282@@ -0,0 +1,127 @@
2283+/*
2284+ * Copyright (C) 2016 Canonical Ltd
2285+ *
2286+ * This program is free software: you can redistribute it and/or modify
2287+ * it under the terms of the GNU Lesser General Public License version 3 as
2288+ * published by the Free Software Foundation.
2289+ *
2290+ * This program is distributed in the hope that it will be useful,
2291+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2292+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2293+ * GNU Lesser General Public License for more details.
2294+ *
2295+ * You should have received a copy of the GNU Lesser General Public License
2296+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2297+ *
2298+ * Authors: Michi Henning <michi.henning@canonical.com>
2299+ */
2300+
2301+#include <unity/storage/registry/internal/ListAccountsHandler.h>
2302+
2303+#include <unity/storage/internal/AccountDetails.h>
2304+#include <unity/storage/registry/internal/qdbus-last-error-msg.h>
2305+
2306+#include <OnlineAccounts/Account>
2307+#include <QDebug>
2308+
2309+using namespace std;
2310+
2311+namespace unity
2312+{
2313+namespace storage
2314+{
2315+namespace registry
2316+{
2317+namespace internal
2318+{
2319+
2320+ListAccountsHandler::ListAccountsHandler(QDBusConnection const& conn,
2321+ QDBusMessage const& msg,
2322+ shared_ptr<storage::internal::InactivityTimer> const& timer)
2323+ : conn_(conn)
2324+ , msg_(msg)
2325+ , manager_("", conn)
2326+ , activity_notifier_(timer)
2327+{
2328+ connect(&manager_, &OnlineAccounts::Manager::ready, this, &ListAccountsHandler::manager_ready);
2329+ connect(&timer_, &QTimer::timeout, this, &ListAccountsHandler::timeout);
2330+ timer_.setSingleShot(true);
2331+ timer_.start(25000); // TODO: Need config for this eventually.
2332+}
2333+
2334+ListAccountsHandler::~ListAccountsHandler() = default;
2335+
2336+namespace
2337+{
2338+
2339+// TODO: This is a hack until Online Accounts is updated to give us the provider ID, provider name, and icon name.
2340+
2341+struct ProviderDetails
2342+{
2343+ char const* bus_name;
2344+ char const* provider_name;
2345+};
2346+
2347+static map<QString, ProviderDetails> const BUS_NAMES =
2348+{
2349+ { "storage-provider-test", { "com.canonical.StorageFramework.Provider.ProviderTest", "Test Provider" } },
2350+ { "com.canonical.scopes.mcloud_mcloud_mcloud", { "com.canonical.StorageFramework.Provider.McloudProvider", "mcloud" } },
2351+ { "storage-provider-owncloud", { "com.canonical.StorageFramework.Provider.OwnCloud", "ownCloud" } },
2352+ { "storage-provider-onedrive", { "com.canonical.StorageFramework.Provider.OnedriveProvider", "OneDrive" } },
2353+};
2354+
2355+} // namespace
2356+
2357+void ListAccountsHandler::manager_ready()
2358+{
2359+ timer_.stop();
2360+ disconnect(this);
2361+ deleteLater();
2362+
2363+ QList<storage::internal::AccountDetails> accounts;
2364+ for (auto const& acct : manager_.availableAccounts())
2365+ {
2366+ auto const it = BUS_NAMES.find(acct->serviceId());
2367+ if (it == BUS_NAMES.end())
2368+ {
2369+ continue;
2370+ }
2371+
2372+ storage::internal::AccountDetails ad;
2373+ ad.busName = it->second.bus_name;
2374+ ad.objectPath = QDBusObjectPath(QStringLiteral("/provider/%1").arg(acct->id()));
2375+ ad.id = acct->id();
2376+ ad.serviceId = acct->serviceId();
2377+ ad.displayName = acct->displayName();
2378+ ad.providerName = it->second.provider_name;
2379+ ad.iconName = "";
2380+
2381+ accounts.append(ad);
2382+ }
2383+
2384+ if (!conn_.send(msg_.createReply(QVariant::fromValue(accounts))))
2385+ {
2386+ auto msg = last_error_msg(conn_);
2387+ qCritical().noquote() << "ListAccounts(): could not send DBus reply" + msg;
2388+ }
2389+}
2390+
2391+void ListAccountsHandler::timeout()
2392+{
2393+ disconnect(this);
2394+ deleteLater();
2395+
2396+ QString err = QString("cannot contact Online Accounts: request timed out after ") +
2397+ QString::number(timer_.interval()) + " ms";
2398+ qCritical().noquote() << err;
2399+ if (!conn_.send(msg_.createErrorReply(QDBusError::Other, err)))
2400+ {
2401+ auto msg = last_error_msg(conn_);
2402+ qCritical().noquote() << "ListAccounts(): could not send DBus error reply" + msg;
2403+ }
2404+}
2405+
2406+} // namespace internal
2407+} // namespace registry
2408+} // namespace storage
2409+} // namespace unity
2410
2411=== added file 'src/registry/internal/RegistryAdaptor.cpp'
2412--- src/registry/internal/RegistryAdaptor.cpp 1970-01-01 00:00:00 +0000
2413+++ src/registry/internal/RegistryAdaptor.cpp 2016-12-12 02:53:43 +0000
2414@@ -0,0 +1,55 @@
2415+/*
2416+ * Copyright (C) 2016 Canonical Ltd
2417+ *
2418+ * This program is free software: you can redistribute it and/or modify
2419+ * it under the terms of the GNU Lesser General Public License version 3 as
2420+ * published by the Free Software Foundation.
2421+ *
2422+ * This program is distributed in the hope that it will be useful,
2423+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2424+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2425+ * GNU Lesser General Public License for more details.
2426+ *
2427+ * You should have received a copy of the GNU Lesser General Public License
2428+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2429+ *
2430+ * Authors: Michi Henning <michi.henning@canonical.com>
2431+ */
2432+
2433+#include <unity/storage/registry/internal/RegistryAdaptor.h>
2434+
2435+#include <unity/storage/registry/internal/ListAccountsHandler.h>
2436+
2437+using namespace std;
2438+
2439+namespace unity
2440+{
2441+namespace storage
2442+{
2443+namespace registry
2444+{
2445+namespace internal
2446+{
2447+
2448+RegistryAdaptor::RegistryAdaptor(QDBusConnection const& conn,
2449+ shared_ptr<storage::internal::InactivityTimer> const& timer,
2450+ QObject* parent)
2451+ : QObject(parent)
2452+ , conn_(conn)
2453+ , timer_(timer)
2454+{
2455+}
2456+
2457+RegistryAdaptor::~RegistryAdaptor() = default;
2458+
2459+QList<unity::storage::internal::AccountDetails> RegistryAdaptor::ListAccounts()
2460+{
2461+ new ListAccountsHandler(conn_, message(), timer_); // Handler deletes itself once done.
2462+ setDelayedReply(true);
2463+ return QList<unity::storage::internal::AccountDetails>();
2464+}
2465+
2466+} // namespace internal
2467+} // namespace registry
2468+} // namespace storage
2469+} // namespace unity
2470
2471=== added file 'src/registry/internal/qdbus-last-error-msg.cpp'
2472--- src/registry/internal/qdbus-last-error-msg.cpp 1970-01-01 00:00:00 +0000
2473+++ src/registry/internal/qdbus-last-error-msg.cpp 2016-12-12 02:53:43 +0000
2474@@ -0,0 +1,49 @@
2475+/*
2476+ * Copyright (C) 2016 Canonical Ltd
2477+ *
2478+ * This program is free software: you can redistribute it and/or modify
2479+ * it under the terms of the GNU Lesser General Public License version 3 as
2480+ * published by the Free Software Foundation.
2481+ *
2482+ * This program is distributed in the hope that it will be useful,
2483+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2484+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2485+ * GNU Lesser General Public License for more details.
2486+ *
2487+ * You should have received a copy of the GNU Lesser General Public License
2488+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2489+ *
2490+ * Authors: Michi Henning <michi.henning@canonical.com>
2491+ */
2492+
2493+#include <unity/storage/registry/internal/qdbus-last-error-msg.h>
2494+
2495+#pragma GCC diagnostic push
2496+#pragma GCC diagnostic ignored "-Wcast-align"
2497+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
2498+#include <QDBusError>
2499+#pragma GCC diagnostic pop
2500+
2501+namespace unity
2502+{
2503+namespace storage
2504+{
2505+namespace registry
2506+{
2507+namespace internal
2508+{
2509+
2510+QString last_error_msg(QDBusConnection const& conn)
2511+{
2512+ auto msg = conn.lastError().message();
2513+ if (!msg.isEmpty())
2514+ {
2515+ msg = ": " + msg;
2516+ }
2517+ return msg;
2518+}
2519+
2520+} // namespace internal
2521+} // namespace registry
2522+} // namespace storage
2523+} // namespace unity
2524
2525=== added file 'src/registry/main.cpp'
2526--- src/registry/main.cpp 1970-01-01 00:00:00 +0000
2527+++ src/registry/main.cpp 2016-12-12 02:53:43 +0000
2528@@ -0,0 +1,95 @@
2529+/*
2530+ * Copyright (C) 2016 Canonical Ltd
2531+ *
2532+ * This program is free software: you can redistribute it and/or modify
2533+ * it under the terms of the GNU Lesser General Public License version 3 as
2534+ * published by the Free Software Foundation.
2535+ *
2536+ * This program is distributed in the hope that it will be useful,
2537+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2538+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2539+ * GNU Lesser General Public License for more details.
2540+ *
2541+ * You should have received a copy of the GNU Lesser General Public License
2542+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2543+ *
2544+ * Authors: Michi Henning <michi.henning@canonical.com>
2545+ */
2546+
2547+#include "registryadaptor.h"
2548+#include <unity/storage/internal/EnvVars.h>
2549+#include <unity/storage/internal/InactivityTimer.h>
2550+#include <unity/storage/internal/TraceMessageHandler.h>
2551+#include <unity/storage/registry/internal/qdbus-last-error-msg.h>
2552+#include <unity/storage/registry/internal/RegistryAdaptor.h>
2553+#include <unity/storage/registry/Registry.h>
2554+
2555+#pragma GCC diagnostic push
2556+#pragma GCC diagnostic ignored "-Wcast-align"
2557+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
2558+#include <QCoreApplication>
2559+#include <QDBusArgument>
2560+#include <QDBusError>
2561+#include <QFileInfo>
2562+#pragma GCC diagnostic pop
2563+
2564+using namespace unity::storage;
2565+using namespace unity::storage::registry::internal;
2566+using namespace std;
2567+
2568+int main(int argc, char* argv[])
2569+{
2570+ auto const prog_name = QFileInfo(argv[0]).fileName();
2571+ internal::TraceMessageHandler message_handler(prog_name);
2572+
2573+ int rc = 1;
2574+ try
2575+ {
2576+ QCoreApplication app(argc, argv);
2577+
2578+ auto conn = QDBusConnection::sessionBus();
2579+
2580+ int const timeout_ms = internal::EnvVars::registry_timeout_ms();
2581+ auto timeout_func = [&app, timeout_ms]
2582+ {
2583+ qInfo().noquote().nospace() << "Exiting after " << QString::number(timeout_ms) << " ms of idle time";
2584+ app.quit();
2585+ };
2586+ auto inactivity_timer = make_shared<unity::storage::internal::InactivityTimer>(timeout_ms, timeout_func);
2587+
2588+ registry::internal::RegistryAdaptor registry_adaptor(conn, inactivity_timer);
2589+ new ::RegistryAdaptor(&registry_adaptor);
2590+
2591+ auto const& object_path = registry::OBJECT_PATH;
2592+ if (!conn.registerObject(object_path, &registry_adaptor))
2593+ {
2594+ auto msg = last_error_msg(conn);
2595+ throw runtime_error(string("Could not register object path ") +
2596+ object_path.toStdString() + msg.toStdString());
2597+ }
2598+
2599+ qDBusRegisterMetaType<unity::storage::internal::AccountDetails>();
2600+ qDBusRegisterMetaType<QList<unity::storage::internal::AccountDetails>>();
2601+
2602+ auto const& bus_name = registry::BUS_NAME;
2603+ if (!conn.registerService(bus_name))
2604+ {
2605+ auto msg = last_error_msg(conn);
2606+ throw runtime_error(string("Could not acquire DBus name ") + bus_name.toStdString() + msg.toStdString());
2607+ }
2608+
2609+ rc = app.exec();
2610+
2611+ if (!conn.unregisterService(bus_name))
2612+ {
2613+ auto msg = last_error_msg(conn);
2614+ throw runtime_error(string("Could not release DBus name ") + bus_name.toStdString() + msg.toStdString());
2615+ }
2616+ }
2617+ catch (std::exception const& e)
2618+ {
2619+ qCritical().noquote() << e.what();
2620+ }
2621+
2622+ return rc;
2623+}
2624
2625=== modified file 'tests/CMakeLists.txt'
2626--- tests/CMakeLists.txt 2016-09-08 08:33:59 +0000
2627+++ tests/CMakeLists.txt 2016-12-12 02:53:43 +0000
2628@@ -1,10 +1,4 @@
2629-# We add -g so we get debug info for the gtest stack frames with gdb.
2630-# The warnings are suppressed so we get a noise-free build for gtest and gmock.
2631-
2632-set(old_cxx_flags ${CMAKE_CXX_FLAGS})
2633-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -Wno-old-style-cast -Wno-missing-field-initializers")
2634 find_package(GMock)
2635-set(CMAKE_CXX_FLAGS ${old_cxx_flags})
2636
2637 configure_file(testsetup.h.in testsetup.h @ONLY)
2638 include_directories(${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
2639@@ -12,6 +6,7 @@
2640 add_subdirectory(utils)
2641
2642 set(unit_test_dirs
2643+ registry
2644 local-client
2645 remote-client
2646 remote-client-v1
2647
2648=== modified file 'tests/copyright/check_copyright.sh'
2649--- tests/copyright/check_copyright.sh 2016-11-04 10:52:10 +0000
2650+++ tests/copyright/check_copyright.sh 2016-12-12 02:53:43 +0000
2651@@ -22,6 +22,8 @@
2652 # Check that we have acceptable license information in our source files.
2653 #
2654
2655+set -eu
2656+
2657 usage()
2658 {
2659 echo "usage: check_copyright dir [ignore_dir]" >&2
2660@@ -31,6 +33,9 @@
2661 [ $# -lt 1 ] && usage
2662 [ $# -gt 2 ] && usage
2663
2664+source_dir="$1"
2665+ignore_dir="${2:-}"
2666+
2667 ignore_pat="\\.sci$|\\.swp$|\\.bzr|debian|qmldir|HACKING|ubsan-suppress|valgrind-suppress|\\.txt$|\\.xml$|\\.in$|\\.dox$|\\.yaml$"
2668
2669 #
2670@@ -39,15 +44,16 @@
2671 # the output with grep -F, so we don't get false positives from licensecheck.
2672 #
2673
2674-[ $# -eq 2 ] && ignore_dir="$2"
2675-
2676-if [ -n "$ignore_dir" ]
2677-then
2678- licensecheck -i "$ignore_pat" -r "$1" | grep -F "$ignore_dir" -v | grep 'No copyright'
2679+licensecheck -i "$ignore_pat" -r "$source_dir" > licensecheck.log
2680+if [ -n "$ignore_dir" ]; then
2681+ cat licensecheck.log | grep -v -F "$ignore_dir" | grep "No copyright" > filtered.log || :
2682 else
2683- licensecheck -i "$ignore_pat" -r "$1" | grep 'No copyright'
2684+ cat licensecheck.log | grep "No copyright" > filtered.log || :
2685 fi
2686
2687-[ $? -eq 0 ] && exit 1
2688+if [ -s filtered.log ]; then
2689+ cat filtered.log
2690+ exit 1
2691+fi
2692
2693 exit 0
2694
2695=== modified file 'tests/headers/CMakeLists.txt'
2696--- tests/headers/CMakeLists.txt 2016-09-08 08:33:59 +0000
2697+++ tests/headers/CMakeLists.txt 2016-12-12 02:53:43 +0000
2698@@ -41,14 +41,14 @@
2699 add_test(stand-alone-${location}-headers
2700 ${CMAKE_CURRENT_SOURCE_DIR}/compile_headers.py
2701 ${extra_defines}
2702- ${public_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fPIC -fsyntax-only -I${root_inc_dir} -I${public_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS} ${extra_inc_dirs}")
2703+ ${public_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fPIC -I${root_inc_dir} -I${public_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS} ${extra_inc_dirs}")
2704
2705 # Test that each internal header compiles stand-alone.
2706 if (IS_DIRECTORY ${internal_inc_dir})
2707 add_test(stand-alone-${location}-internal-headers
2708 ${CMAKE_CURRENT_SOURCE_DIR}/compile_headers.py
2709 ${extra_defines}
2710- ${internal_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fPIC -fsyntax-only -I${root_inc_dir} -I${internal_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS} ${extra_inc_dirs}")
2711+ ${internal_inc_dir} ${CMAKE_CXX_COMPILER} "${CMAKE_CXX_COMPILER_ARG1} -fPIC -I${root_inc_dir} -I${internal_inc_dir} ${other_inc_dirs} ${CMAKE_CXX_FLAGS} ${extra_inc_dirs}")
2712 endif()
2713
2714 if (NOT ${public_inc_dir} MATCHES "/internal/")
2715
2716=== modified file 'tests/headers/compile_headers.py'
2717--- tests/headers/compile_headers.py 2016-08-22 04:35:33 +0000
2718+++ tests/headers/compile_headers.py 2016-12-12 02:53:43 +0000
2719@@ -52,7 +52,6 @@
2720 import shlex
2721 import subprocess
2722 import sys
2723-import tempfile
2724 import concurrent.futures, multiprocessing
2725
2726 #
2727@@ -74,16 +73,20 @@
2728 #
2729 def run_compiler(hdr, compiler, copts, define, verbose, hdr_dir):
2730 try:
2731- src = tempfile.NamedTemporaryFile(suffix='.cpp', dir='.')
2732+ compile_dir = "./.header_tests"
2733+ os.makedirs(compile_dir, exist_ok=True)
2734+ src_name = os.path.join(compile_dir, hdr) + ".cpp"
2735+
2736+ if not os.path.exists(src_name):
2737+ src_fd = os.open(src_name, os.O_WRONLY | os.O_CREAT)
2738+ src = os.fdopen(src_fd, 'w')
2739+ src.write("#include <" + hdr + ">" + "\n")
2740+ src.write("#include <" + hdr + ">" + "\n") # To test that double-inclusion is safe
2741
2742 # Add any extra defines to the command line.
2743 for flag in define:
2744 copts = "-D" + flag + " " + copts
2745
2746- src.write(bytes("#include <" + hdr + ">" + "\n", 'UTF-8'))
2747- src.flush() # Need this to make the file visible
2748- src_name = os.path.join('.', src.name)
2749-
2750 if verbose:
2751 print(compiler + " -c " + src_name + " " + copts)
2752
2753@@ -91,13 +94,13 @@
2754 if status != 0:
2755 message("cannot compile \"" + hdr + "\"") # Yes, write to stdout because this is expected output
2756
2757- obj = os.path.splitext(src_name)[0] + ".o"
2758+ obj = hdr + ".o"
2759 try:
2760 os.unlink(obj)
2761 except:
2762 pass
2763
2764- gcov = os.path.splitext(src_name)[0] + ".gcno"
2765+ gcov = hdr + ".gcno"
2766 try:
2767 os.unlink(gcov)
2768 except:
2769
2770=== modified file 'tests/local-client/local-client_test.cpp'
2771--- tests/local-client/local-client_test.cpp 2016-08-26 04:45:56 +0000
2772+++ tests/local-client/local-client_test.cpp 2016-12-12 02:53:43 +0000
2773@@ -21,7 +21,11 @@
2774 #include <unity/storage/qt/client/internal/local_client/boost_filesystem.h>
2775 #include <unity/storage/qt/client/internal/local_client/tmpfile_prefix.h>
2776
2777+#pragma GCC diagnostic push
2778+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
2779 #include <gtest/gtest.h>
2780+#pragma GCC diagnostic pop
2781+
2782 #include <QCoreApplication>
2783 #include <QFile>
2784 #include <QFutureWatcher>
2785
2786=== modified file 'tests/provider-AccountData/AccountData_test.cpp'
2787--- tests/provider-AccountData/AccountData_test.cpp 2016-09-28 11:58:35 +0000
2788+++ tests/provider-AccountData/AccountData_test.cpp 2016-12-12 02:53:43 +0000
2789@@ -22,7 +22,11 @@
2790
2791 #include <utils/DBusEnvironment.h>
2792
2793+#pragma GCC diagnostic push
2794+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
2795 #include <gtest/gtest.h>
2796+#pragma GCC diagnostic pop
2797+
2798 #include <OnlineAccounts/Account>
2799 #include <OnlineAccounts/Manager>
2800 #include <QCoreApplication>
2801
2802=== modified file 'tests/provider-DBusPeerCache/DBusPeerCache_test.cpp'
2803--- tests/provider-DBusPeerCache/DBusPeerCache_test.cpp 2016-07-28 03:10:57 +0000
2804+++ tests/provider-DBusPeerCache/DBusPeerCache_test.cpp 2016-12-12 02:53:43 +0000
2805@@ -20,7 +20,11 @@
2806
2807 #include <utils/DBusEnvironment.h>
2808
2809+#pragma GCC diagnostic push
2810+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
2811 #include <gtest/gtest.h>
2812+#pragma GCC diagnostic pop
2813+
2814 #include <OnlineAccounts/Account>
2815 #include <OnlineAccounts/Manager>
2816 #include <QCoreApplication>
2817
2818=== modified file 'tests/provider-ProviderInterface/TestProvider.cpp'
2819--- tests/provider-ProviderInterface/TestProvider.cpp 2016-11-03 02:43:43 +0000
2820+++ tests/provider-ProviderInterface/TestProvider.cpp 2016-12-12 02:53:43 +0000
2821@@ -87,7 +87,7 @@
2822 boost::future<Item> TestUploadJob::finish()
2823 {
2824 boost::promise<Item> p;
2825- printf("TestUploadJob::finish(): %d read of expected %d\n", (int) bytes_read_, (int) size_);
2826+ printf("TestUploadJob::finish(): %d read of expected %d\n", int(bytes_read_), int(size_));
2827 notifier_.setEnabled(false);
2828 drain();
2829 if (bytes_read_ == size_)
2830@@ -139,7 +139,7 @@
2831
2832 void TestUploadJob::read_some()
2833 {
2834- printf("TestUploadJob::read_some(): %d read of expected %d\n", (int) bytes_read_, (int) size_);
2835+ printf("TestUploadJob::read_some(): %d read of expected %d\n", int(bytes_read_), int(size_));
2836
2837 char buf[5];
2838 ssize_t n_read = read(read_socket(), buf, sizeof(buf));
2839@@ -248,7 +248,7 @@
2840 boost::future<void> TestDownloadJob::finish()
2841 {
2842 boost::promise<void> p;
2843- if (bytes_written_ < (ssize_t)data_.size())
2844+ if (bytes_written_ < ssize_t(data_.size()))
2845 {
2846 p.set_exception(LogicException("Not all data read"));
2847 }
2848@@ -261,14 +261,14 @@
2849
2850 void TestDownloadJob::write_some()
2851 {
2852- if (bytes_written_ >= (ssize_t)data_.size()) {
2853+ if (bytes_written_ >= ssize_t(data_.size())) {
2854 report_complete();
2855 timer_.stop();
2856 return;
2857 }
2858
2859 ssize_t n_written = write(write_socket(), data_.data() + bytes_written_,
2860- min(data_.size() - bytes_written_, (size_t)2));
2861+ min(data_.size() - bytes_written_, size_t(2)));
2862 if (n_written < 0)
2863 {
2864 int error_code = errno;
2865
2866=== added directory 'tests/registry'
2867=== added file 'tests/registry/CMakeLists.txt'
2868--- tests/registry/CMakeLists.txt 1970-01-01 00:00:00 +0000
2869+++ tests/registry/CMakeLists.txt 2016-12-12 02:53:43 +0000
2870@@ -0,0 +1,20 @@
2871+add_executable(registry_test registry_test.cpp)
2872+#set_target_properties(remote-client_test PROPERTIES AUTOMOC TRUE)
2873+
2874+#add_definitions(-DTEST_DIR="${CMAKE_CURRENT_BINARY_DIR}" -DBOOST_THREAD_VERSION=4)
2875+#include_directories(${GLIB_DEPS_INCLUDE_DIRS})
2876+
2877+#target_link_libraries(remote-client_test
2878+# storage-framework-provider
2879+# storage-framework-qt-client-v2
2880+# Qt5::Network
2881+# Qt5::Test
2882+# ${Boost_LIBRARIES}
2883+# ${GLIB_DEPS_LIBRARIES}
2884+# testutils
2885+# gtest
2886+#)
2887+add_test(registry registry_test)
2888+#add_dependencies(remote-client_test qt-client-all-headers provider-test)
2889+
2890+#set(UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} PARENT_SCOPE)
2891
2892=== added file 'tests/registry/registry_test.cpp'
2893--- tests/registry/registry_test.cpp 1970-01-01 00:00:00 +0000
2894+++ tests/registry/registry_test.cpp 2016-12-12 02:53:43 +0000
2895@@ -0,0 +1,27 @@
2896+/*
2897+ * Copyright (C) 2016 Canonical Ltd
2898+ *
2899+ * This program is free software: you can redistribute it and/or modify
2900+ * it under the terms of the GNU Lesser General Public License version 3 as
2901+ * published by the Free Software Foundation.
2902+ *
2903+ * This program is distributed in the hope that it will be useful,
2904+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2905+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2906+ * GNU Lesser General Public License for more details.
2907+ *
2908+ * You should have received a copy of the GNU Lesser General Public License
2909+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2910+ *
2911+ * Authors: Michi Henning <michi.henning@canonical.com>
2912+ */
2913+
2914+int main(int argc, char** argv)
2915+{
2916+#if 0
2917+ QCoreApplication app(argc, argv);
2918+
2919+ ::testing::InitGoogleTest(&argc, argv);
2920+ return RUN_ALL_TESTS();
2921+#endif
2922+}
2923
2924=== modified file 'tests/remote-client-v1/remote-client-v1_test.cpp'
2925--- tests/remote-client-v1/remote-client-v1_test.cpp 2016-09-26 02:37:03 +0000
2926+++ tests/remote-client-v1/remote-client-v1_test.cpp 2016-12-12 02:53:43 +0000
2927@@ -56,7 +56,7 @@
2928 void SetUp() override
2929 {
2930 dbus_.reset(new DBusEnvironment);
2931- dbus_->add_demo_provider("google-drive-scope");
2932+ dbus_->add_demo_provider("storage-provider-test");
2933 dbus_->start_services();
2934 }
2935
2936@@ -150,7 +150,7 @@
2937 }
2938 for (auto acc : accounts)
2939 {
2940- if (acc->owner_id() == "google-drive-scope")
2941+ if (acc->owner_id() == "storage-provider-test")
2942 {
2943 return acc;
2944 }
2945@@ -198,8 +198,8 @@
2946 auto acc = get_account(runtime);
2947 EXPECT_EQ(runtime, acc->runtime());
2948 EXPECT_EQ("", acc->owner());
2949- EXPECT_EQ("google-drive-scope", acc->owner_id());
2950- EXPECT_EQ("Fake google account", acc->description());
2951+ EXPECT_EQ("storage-provider-test", acc->owner_id());
2952+ EXPECT_EQ("Fake test account", acc->description());
2953 }
2954
2955 TEST_F(RuntimeTest, roots)
2956
2957=== modified file 'tests/remote-client/CMakeLists.txt'
2958--- tests/remote-client/CMakeLists.txt 2016-09-08 08:33:59 +0000
2959+++ tests/remote-client/CMakeLists.txt 2016-12-12 02:53:43 +0000
2960@@ -15,6 +15,6 @@
2961 gtest
2962 )
2963 add_test(remote-client remote-client_test)
2964-add_dependencies(remote-client_test qt-client-all-headers provider-test)
2965+add_dependencies(remote-client_test qt-client-all-headers storage-framework-registry)
2966
2967 set(UNIT_TEST_TARGETS ${UNIT_TEST_TARGETS} PARENT_SCOPE)
2968
2969=== modified file 'tests/remote-client/remote-client_test.cpp'
2970--- tests/remote-client/remote-client_test.cpp 2016-11-04 07:33:07 +0000
2971+++ tests/remote-client/remote-client_test.cpp 2016-12-12 02:53:43 +0000
2972@@ -22,7 +22,11 @@
2973 #include <utils/gtest_printer.h>
2974 #include <utils/ProviderFixture.h>
2975
2976+#pragma GCC diagnostic push
2977+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
2978 #include <gtest/gtest.h>
2979+#pragma GCC diagnostic pop
2980+
2981 #include <QSignalSpy>
2982
2983 #include <unordered_set>
2984@@ -121,77 +125,77 @@
2985
2986 {
2987 auto acc = runtime_->make_test_account(service_connection_->baseService(), object_path(),
2988- "id", "sid", "displayName");
2989+ 99, "sid", "name");
2990 EXPECT_TRUE(acc.isValid());
2991 EXPECT_EQ(service_connection_->baseService(), acc.busName());
2992 EXPECT_EQ(object_path(), acc.objectPath());
2993- EXPECT_EQ("displayName", acc.displayName());
2994+ EXPECT_EQ("name", acc.displayName());
2995
2996 // Copy constructor
2997 Account a2(acc);
2998 EXPECT_TRUE(a2.isValid());
2999 EXPECT_EQ(service_connection_->baseService(), a2.busName());
3000 EXPECT_EQ(object_path(), a2.objectPath());
3001- EXPECT_EQ("displayName", a2.displayName());
3002+ EXPECT_EQ("name", a2.displayName());
3003
3004 // Move constructor
3005 Account a3(move(a2));
3006 EXPECT_TRUE(a3.isValid());
3007 EXPECT_EQ(service_connection_->baseService(), a3.busName());
3008 EXPECT_EQ(object_path(), a3.objectPath());
3009- EXPECT_EQ("displayName", a3.displayName());
3010+ EXPECT_EQ("name", a3.displayName());
3011
3012 // Moved-from object must be invalid
3013 EXPECT_FALSE(a2.isValid());
3014
3015 // Moved-from object must be assignable
3016 auto a4 = runtime_->make_test_account(service_connection_->baseService(), object_path(),
3017- "id4", "sid4", "displayName4");
3018+ 99, "sid4", "name4");
3019 a2 = a4;
3020 EXPECT_TRUE(a2.isValid());
3021 EXPECT_EQ(service_connection_->baseService(), a2.busName());
3022 EXPECT_EQ(object_path(), a2.objectPath());
3023- EXPECT_EQ("displayName4", a2.displayName());
3024+ EXPECT_EQ("name4", a2.displayName());
3025 }
3026
3027 {
3028- auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "id", "sid", "dn");
3029- auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "id2", "sid2", "dn2");
3030+ auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 99, "sid", "dn");
3031+ auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 100, "sid2", "n2");
3032
3033 // Copy assignment
3034 a1 = a2;
3035 EXPECT_TRUE(a2.isValid());
3036 EXPECT_EQ(service_connection_->baseService(), a1.busName());
3037 EXPECT_EQ(object_path(), a1.objectPath());
3038- EXPECT_EQ("dn2", a1.displayName());
3039+ EXPECT_EQ("n2", a1.displayName());
3040
3041 // Self-assignment
3042 a2 = a2;
3043 EXPECT_TRUE(a2.isValid());
3044 EXPECT_EQ(service_connection_->baseService(), a1.busName());
3045 EXPECT_EQ(object_path(), a1.objectPath());
3046- EXPECT_EQ("dn2", a1.displayName());
3047+ EXPECT_EQ("n2", a1.displayName());
3048
3049 // Move assignment
3050 auto a3 = runtime_->make_test_account(service_connection_->baseService(), object_path(),
3051- "id3", "sid3", "dn3");
3052+ 101, "sid3", "n3");
3053 a1 = move(a3);
3054 EXPECT_TRUE(a1.isValid());
3055 EXPECT_EQ(service_connection_->baseService(), a1.busName());
3056 EXPECT_EQ(object_path(), a1.objectPath());
3057- EXPECT_EQ("dn3", a1.displayName());
3058+ EXPECT_EQ("n3", a1.displayName());
3059
3060 // Moved-from object must be invalid
3061 EXPECT_FALSE(a3.isValid());
3062
3063 // Moved-from object must be assignable
3064 auto a4 = runtime_->make_test_account(service_connection_->baseService(), object_path(),
3065- "id4", "sid4", "dn4");
3066+ 102, "sid4", "n4");
3067 a2 = a4;
3068 EXPECT_TRUE(a2.isValid());
3069 EXPECT_EQ(service_connection_->baseService(), a2.busName());
3070 EXPECT_EQ(object_path(), a2.objectPath());
3071- EXPECT_EQ("dn4", a2.displayName());
3072+ EXPECT_EQ("n4", a2.displayName());
3073 }
3074 }
3075
3076@@ -231,8 +235,8 @@
3077
3078 {
3079 // a1 < a2 for ID
3080- auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "a", "x", "x");
3081- auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "b", "x", "x");
3082+ auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 1, "x", "x");
3083+ auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 2, "x", "x");
3084
3085 EXPECT_FALSE(a1 == a2);
3086 EXPECT_TRUE(a1 != a2);
3087@@ -252,8 +256,8 @@
3088
3089 {
3090 // a1 < a2 for service ID
3091- auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "a", "a", "x");
3092- auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "a", "b", "x");
3093+ auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 1, "a", "x");
3094+ auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 1, "b", "x");
3095
3096 EXPECT_FALSE(a1 == a2);
3097 EXPECT_TRUE(a1 != a2);
3098@@ -273,8 +277,8 @@
3099
3100 {
3101 // a1 < a2 for display name
3102- auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "a", "a", "a");
3103- auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "a", "a", "b");
3104+ auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 1, "a", "a");
3105+ auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 1, "a", "b");
3106
3107 EXPECT_FALSE(a1 == a2);
3108 EXPECT_TRUE(a1 != a2);
3109@@ -294,8 +298,8 @@
3110
3111 {
3112 // a1 == a2
3113- auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "a", "a", "a");
3114- auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "a", "a", "a");
3115+ auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 1, "a", "a");
3116+ auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 1, "a", "a");
3117
3118 EXPECT_TRUE(a1 == a2);
3119 EXPECT_FALSE(a1 != a2);
3120@@ -319,14 +323,14 @@
3121 unordered_set<Account>(); // Just to show that this works.
3122
3123 Account a1;
3124- EXPECT_EQ(0, hash<Account>()(a1));
3125- EXPECT_EQ(0, a1.hash());
3126- EXPECT_EQ(0, qHash(a1));
3127+ EXPECT_EQ(0u, hash<Account>()(a1));
3128+ EXPECT_EQ(0u, a1.hash());
3129+ EXPECT_EQ(0u, qHash(a1));
3130
3131- auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "a", "a", "a");
3132+ auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 1, "a", "a");
3133 // Due to different return types (size_t vs uint), hash() and qHash() do not return the same value.
3134- EXPECT_NE(0, a2.hash());
3135- EXPECT_NE(0, qHash(a2));
3136+ EXPECT_NE(0u, a2.hash());
3137+ EXPECT_NE(0u, qHash(a2));
3138 }
3139
3140 TEST_F(AccountTest, accounts)
3141@@ -347,17 +351,29 @@
3142 EXPECT_EQ(AccountsJob::Status::Finished, j->status());
3143 EXPECT_EQ(StorageError::Type::NoError, j->error().type());
3144
3145- EXPECT_TRUE(runtime_->connection().isConnected()); // Just for coverage.
3146-
3147 auto accounts = j->accounts();
3148+ EXPECT_GT(accounts.size(), 0);
3149
3150- // We don't check the contents of accounts here because we are using the real online accounts manager
3151- // in this test. This means that the number and kind of accounts that are returned depends
3152- // on what provider accounts the test user has configured.
3153+ // The fake online accounts service includes a "com.canonical.StorageFramework.Provider.ProviderTest" account.
3154+ bool found = false;
3155+ for (auto const& a : accounts)
3156+ {
3157+ qDebug() << a.busName();
3158+ if (a.busName() == "com.canonical.StorageFramework.Provider.ProviderTest")
3159+ {
3160+ found = true;
3161+ EXPECT_EQ("Test Provider", a.providerName());
3162+ // TODO: add tests for the other account properties.
3163+ break;
3164+ }
3165+ }
3166+ EXPECT_TRUE(found);
3167 }
3168
3169 TEST_F(AccountTest, runtime_destroyed)
3170 {
3171+ EXPECT_TRUE(runtime_->connection().isConnected()); // Just for coverage.
3172+
3173 EXPECT_EQ(StorageError::Type::NoError, runtime_->shutdown().type()); // Destroy runtime.
3174
3175 AccountsJob* j = runtime_->accounts();
3176@@ -504,11 +520,23 @@
3177 QSignalSpy ready_spy(j.get(), &ItemListJob::itemsReady);
3178 QSignalSpy status_spy(j.get(), &ItemListJob::statusChanged);
3179 status_spy.wait(SIGNAL_WAIT_TIME);
3180- auto arg = status_spy.takeFirst();
3181-
3182- // Bad metadata is ignored, so status is finished, and itemsReady was never called.
3183- EXPECT_EQ(ItemListJob::Status::Finished, qvariant_cast<ItemListJob::Status>(arg.at(0)));
3184- EXPECT_EQ(0, status_spy.count());
3185+ {
3186+ auto arg = status_spy.takeFirst();
3187+ EXPECT_EQ(ItemListJob::Status::Error, qvariant_cast<ItemListJob::Status>(arg.at(0)));
3188+ }
3189+
3190+ if (ready_spy.count() != 1)
3191+ {
3192+ ready_spy.wait(SIGNAL_WAIT_TIME);
3193+ }
3194+ auto arg = ready_spy.takeFirst();
3195+ auto items = qvariant_cast<QList<Item>>(arg.at(0));
3196+ EXPECT_EQ(0, items.size());
3197+
3198+ EXPECT_EQ(ItemListJob::Status::Error, j->status());
3199+ EXPECT_EQ(StorageError::Type::LocalCommsError, j->error().type());
3200+ EXPECT_EQ("LocalCommsError: Account::roots(): provider returned non-root item type: 0 (id = root_id)",
3201+ j->error().errorString());
3202 }
3203
3204 TEST_F(GetTest, basic)
3205@@ -679,8 +707,9 @@
3206 spy.wait(SIGNAL_WAIT_TIME);
3207
3208 EXPECT_EQ(ItemJob::Status::Error, j->status());
3209- EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: "
3210- "file or folder must have at least one parent ID", j->error().errorString());
3211+ EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider (id = child_id): "
3212+ "file or folder must have at least one parent ID"
3213+ , j->error().errorString());
3214 }
3215
3216 TEST_F(MetadataTest, empty_parent)
3217@@ -693,8 +722,9 @@
3218 spy.wait(SIGNAL_WAIT_TIME);
3219
3220 EXPECT_EQ(ItemJob::Status::Error, j->status());
3221- EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: "
3222- "parent_id of file or folder cannot be empty", j->error().errorString());
3223+ EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider (id = child_id): "
3224+ "parent_id of file or folder cannot be empty",
3225+ j->error().errorString());
3226 }
3227
3228 TEST_F(MetadataTest, root_with_parent)
3229@@ -707,8 +737,9 @@
3230 spy.wait(SIGNAL_WAIT_TIME);
3231
3232 EXPECT_EQ(ItemJob::Status::Error, j->status());
3233- EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: "
3234- "parent_ids of root must be empty", j->error().errorString());
3235+ EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider (id = root_id): "
3236+ "parent_ids of root must be empty",
3237+ j->error().errorString());
3238 }
3239
3240 TEST_F(MetadataTest, empty_name)
3241@@ -721,8 +752,9 @@
3242 spy.wait(SIGNAL_WAIT_TIME);
3243
3244 EXPECT_EQ(ItemJob::Status::Error, j->status());
3245- EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: "
3246- "name cannot be empty", j->error().errorString());
3247+ EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider (id = child_id): "
3248+ "name cannot be empty",
3249+ j->error().errorString());
3250 }
3251
3252 TEST_F(MetadataTest, empty_etag)
3253@@ -735,8 +767,9 @@
3254 spy.wait(SIGNAL_WAIT_TIME);
3255
3256 EXPECT_EQ(ItemJob::Status::Error, j->status());
3257- EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: "
3258- "etag of a file cannot be empty", j->error().errorString());
3259+ EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider (id = child_id): "
3260+ "etag of a file cannot be empty",
3261+ j->error().errorString());
3262 }
3263
3264 TEST_F(MetadataTest, unknown_key)
3265@@ -762,8 +795,9 @@
3266 spy.wait(SIGNAL_WAIT_TIME);
3267
3268 EXPECT_EQ(ItemJob::Status::Error, j->status());
3269- EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: "
3270- "missing key \"size_in_bytes\" in metadata for \"child_id\"", j->error().errorString());
3271+ EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider (id = child_id): "
3272+ "missing key \"size_in_bytes\" in metadata",
3273+ j->error().errorString());
3274 }
3275
3276 TEST_F(MetadataTest, wrong_type_for_time)
3277@@ -776,8 +810,9 @@
3278 spy.wait(SIGNAL_WAIT_TIME);
3279
3280 EXPECT_EQ(ItemJob::Status::Error, j->status());
3281- EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: last_modified_time: "
3282- "expected value of type QString, but received value of type qlonglong", j->error().errorString());
3283+ EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider (id = child_id): "
3284+ "last_modified_time: expected value of type QString, but received value of type qlonglong",
3285+ j->error().errorString());
3286 }
3287
3288 TEST_F(MetadataTest, bad_parse_for_time)
3289@@ -790,8 +825,9 @@
3290 spy.wait(SIGNAL_WAIT_TIME);
3291
3292 EXPECT_EQ(ItemJob::Status::Error, j->status());
3293- EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: last_modified_time: "
3294- "value \"xyz\" does not parse as ISO-8601 date", j->error().errorString());
3295+ EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider (id = child_id): "
3296+ "last_modified_time: value \"xyz\" does not parse as ISO-8601 date",
3297+ j->error().errorString());
3298 }
3299
3300 TEST_F(MetadataTest, missing_timezone)
3301@@ -804,8 +840,9 @@
3302 spy.wait(SIGNAL_WAIT_TIME);
3303
3304 EXPECT_EQ(ItemJob::Status::Error, j->status());
3305- EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: last_modified_time: "
3306- "value \"2007-04-05T14:30\" lacks a time zone specification", j->error().errorString());
3307+ EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider (id = child_id): "
3308+ "last_modified_time: value \"2007-04-05T14:30\" lacks a time zone specification",
3309+ j->error().errorString());
3310 }
3311
3312 TEST_F(MetadataTest, wrong_type_for_size)
3313@@ -818,8 +855,9 @@
3314 spy.wait(SIGNAL_WAIT_TIME);
3315
3316 EXPECT_EQ(ItemJob::Status::Error, j->status());
3317- EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: size_in_bytes: "
3318- "expected value of type qlonglong, but received value of type QString", j->error().errorString());
3319+ EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider (id = child_id): "
3320+ "size_in_bytes: expected value of type qlonglong, but received value of type QString",
3321+ j->error().errorString());
3322 }
3323
3324 TEST_F(MetadataTest, negative_size)
3325@@ -832,8 +870,9 @@
3326 spy.wait(SIGNAL_WAIT_TIME);
3327
3328 EXPECT_EQ(ItemJob::Status::Error, j->status());
3329- EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider: size_in_bytes: "
3330- "expected value >= 0, but received -1", j->error().errorString());
3331+ EXPECT_EQ("LocalCommsError: Account::get(): received invalid metadata from provider (id = child_id): "
3332+ "size_in_bytes: expected value >= 0, but received -1",
3333+ j->error().errorString());
3334 }
3335
3336 TEST_F(DeleteTest, basic)
3337@@ -1121,9 +1160,9 @@
3338
3339 unordered_set<Item>(); // Just to show that this works.
3340
3341- EXPECT_EQ(0, hash<Item>()(i1));
3342- EXPECT_EQ(0, i1.hash());
3343- EXPECT_EQ(0, qHash(i1));
3344+ EXPECT_EQ(0u, hash<Item>()(i1));
3345+ EXPECT_EQ(0u, i1.hash());
3346+ EXPECT_EQ(0u, qHash(i1));
3347 }
3348
3349 {
3350@@ -1155,15 +1194,15 @@
3351 EXPECT_FALSE(i2 > i1);
3352 EXPECT_FALSE(i2 >= i1);
3353
3354- EXPECT_NE(0, i1.hash());
3355- EXPECT_NE(0, qHash(i1));
3356+ EXPECT_NE(0u, i1.hash());
3357+ EXPECT_NE(0u, qHash(i1));
3358 }
3359
3360 {
3361 // Both items valid with identical metadata, but different accounts (a1 < a2).
3362
3363- auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "a", "x", "x");
3364- auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), "b", "x", "x");
3365+ auto a1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 1, "x", "x");
3366+ auto a2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 2, "x", "x");
3367
3368 Item i1;
3369 Item i2;
3370@@ -1485,7 +1524,7 @@
3371 auto arg = spy.takeFirst();
3372 EXPECT_EQ(ItemListJob::Status::Error, qvariant_cast<ItemListJob::Status>(arg.at(0)));
3373
3374- EXPECT_EQ("Item::parents(): provider returned a file as a parent", j->error().message());
3375+ EXPECT_EQ("Item::parents(): provider returned a file as a parent (id = root_id)", j->error().message());
3376 }
3377 }
3378
3379@@ -1639,11 +1678,12 @@
3380 {
3381 set_provider(unique_ptr<provider::ProviderBase>(new MockProvider()));
3382
3383- auto test_account = runtime_->make_test_account(service_connection_->baseService(), object_path(), "test_account");
3384+ auto acc1 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 1);
3385+ auto acc2 = runtime_->make_test_account(service_connection_->baseService(), object_path(), 2);
3386
3387 Item root1;
3388 {
3389- unique_ptr<ItemJob> j(test_account.get("root_id"));
3390+ unique_ptr<ItemJob> j(acc1.get("root_id"));
3391 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
3392 spy.wait(SIGNAL_WAIT_TIME);
3393 root1 = j->item();
3394@@ -1652,7 +1692,7 @@
3395
3396 Item root2;
3397 {
3398- unique_ptr<ItemJob> j(acc_.get("root_id"));
3399+ unique_ptr<ItemJob> j(acc2.get("root_id"));
3400 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
3401 spy.wait(SIGNAL_WAIT_TIME);
3402 root2 = j->item();
3403@@ -1661,7 +1701,7 @@
3404
3405 Item child;
3406 {
3407- unique_ptr<ItemJob> j(acc_.get("child_id"));
3408+ unique_ptr<ItemJob> j(acc2.get("child_id"));
3409 QSignalSpy spy(j.get(), &ItemJob::statusChanged);
3410 spy.wait(SIGNAL_WAIT_TIME);
3411 child = j->item();
3412@@ -1751,7 +1791,9 @@
3413 EXPECT_FALSE(j->isValid());
3414 EXPECT_EQ(ItemJob::Status::Error, j->status());
3415 EXPECT_EQ(StorageError::Type::LocalCommsError, j->error().type());
3416- EXPECT_EQ("LocalCommsError: Item::copy(): source and target item type differ", j->error().errorString());
3417+ EXPECT_EQ("LocalCommsError: Item::copy()provider error: source and target item type differ "
3418+ "(source id = child_id, target id = new_item_id)",
3419+ j->error().errorString());
3420 }
3421
3422 TEST_F(MoveTest, basic)
3423@@ -1863,7 +1905,8 @@
3424 EXPECT_EQ(ItemJob::Status::Error, j->status());
3425 EXPECT_EQ(StorageError::Type::LocalCommsError, j->error().type());
3426 EXPECT_EQ("LocalCommsError", j->error().name());
3427- EXPECT_EQ("LocalCommsError: Item::move(): impossible root item returned by provider", j->error().errorString());
3428+ EXPECT_EQ("LocalCommsError: Item::move(): impossible root item returned by provider (id = root_id)",
3429+ j->error().errorString());
3430 }
3431
3432 TEST_F(MoveTest, type_mismatch)
3433@@ -1899,7 +1942,8 @@
3434 EXPECT_FALSE(j->isValid());
3435 EXPECT_EQ(ItemJob::Status::Error, j->status());
3436 EXPECT_EQ(StorageError::Type::LocalCommsError, j->error().type());
3437- EXPECT_EQ("LocalCommsError: Item::move(): provider error: source and target item type differ",
3438+ EXPECT_EQ("LocalCommsError: Item::move(): provider error: source and target item type differ "
3439+ "(source id = child_id, target id = child_id)",
3440 j->error().errorString());
3441 }
3442
3443@@ -2094,7 +2138,7 @@
3444 auto status = qvariant_cast<ItemJob::Status>(arg.at(0));
3445 EXPECT_EQ(ItemJob::Status::Error, status);
3446
3447- EXPECT_EQ("LocalCommsError: Item::createFolder(): impossible file item returned by provider",
3448+ EXPECT_EQ("LocalCommsError: Item::createFolder(): impossible file item returned by provider (id = new_folder_id)",
3449 j->error().errorString());
3450 }
3451
3452@@ -2157,7 +2201,10 @@
3453 QSignalSpy ready_spy(j.get(), &ItemListJob::itemsReady);
3454 QSignalSpy status_spy(j.get(), &ItemListJob::statusChanged);
3455 status_spy.wait(SIGNAL_WAIT_TIME);
3456- ASSERT_EQ(0, ready_spy.count());
3457+ if (ready_spy.count() == 0)
3458+ {
3459+ ASSERT_TRUE(ready_spy.wait(SIGNAL_WAIT_TIME));
3460+ }
3461
3462 EXPECT_EQ(ItemListJob::Status::Finished, j->status());
3463
3464@@ -2303,7 +2350,8 @@
3465 auto arg = spy.takeFirst();
3466 EXPECT_EQ(ItemListJob::Status::Error, qvariant_cast<ItemListJob::Status>(arg.at(0)));
3467
3468- EXPECT_EQ("LocalCommsError: Item::list(): impossible root item returned by provider", j->error().errorString());
3469+ EXPECT_EQ("LocalCommsError: Item::list(): impossible root item returned by provider (id = child_id)",
3470+ j->error().errorString());
3471 }
3472
3473 TEST_F(ListTest, runtime_destroyed_while_item_list_job_running)
3474@@ -3026,7 +3074,7 @@
3475
3476 unique_ptr<Uploader> uploader(child.createUploader(Item::ConflictPolicy::IgnoreConflict, 20));
3477 EXPECT_FALSE(uploader->isValid());
3478- EXPECT_EQ(Downloader::Status::Error, uploader->status());
3479+ EXPECT_EQ(Uploader::Status::Error, uploader->status());
3480 EXPECT_EQ(StorageError::RuntimeDestroyed, uploader->error().type());
3481 EXPECT_EQ("RuntimeDestroyed: Item::createUploader(): Runtime was destroyed previously",
3482 uploader->error().errorString());
3483@@ -3370,7 +3418,8 @@
3484
3485 EXPECT_EQ(Uploader::Status::Error, uploader->status());
3486 EXPECT_EQ(StorageError::Type::LocalCommsError, uploader->error().type());
3487- EXPECT_EQ("Item::createUploader(): impossible folder item returned by provider", uploader->error().message());
3488+ EXPECT_EQ("Item::createUploader(): impossible folder item returned by provider (id = some_id)",
3489+ uploader->error().message());
3490 }
3491
3492 TEST_F(UploadTest, cancel_success)
3493@@ -3702,7 +3751,8 @@
3494 EXPECT_EQ(Uploader::Status::Error, qvariant_cast<Uploader::Status>(arg.at(0)));
3495
3496 EXPECT_EQ(StorageError::Type::LocalCommsError, uploader->error().type());
3497- EXPECT_EQ("Item::createFile(): impossible folder item returned by provider", uploader->error().message());
3498+ EXPECT_EQ("Item::createFile(): impossible folder item returned by provider (id = some_id)",
3499+ uploader->error().message());
3500 }
3501
3502 TEST_F(CreateFileTest, exists)
3503
3504=== modified file 'tests/utils/DBusEnvironment.cpp'
3505--- tests/utils/DBusEnvironment.cpp 2016-08-04 10:12:01 +0000
3506+++ tests/utils/DBusEnvironment.cpp 2016-12-12 02:53:43 +0000
3507@@ -17,6 +17,7 @@
3508 */
3509
3510 #include "DBusEnvironment.h"
3511+#include <unity/storage/registry/Registry.h>
3512
3513 #include <testsetup.h>
3514
3515@@ -27,6 +28,9 @@
3516 char const ACCOUNTS_BUS_NAME[] = "com.ubuntu.OnlineAccounts.Manager";
3517 char const FAKE_ACCOUNTS_SERVICE[] = TEST_SRC_DIR "/utils/fake-online-accounts-daemon.py";
3518
3519+char const REGISTRY_TEST_BUS_NAME[] = "com.ubuntu.StorageFramework.TestRegistry";
3520+char const REGISTRY_SERVICE[] = TEST_BIN_DIR "/../src/registry/storage-framework-registry";
3521+
3522 char const DEMO_PROVIDER_BUS_NAME[] = "com.canonical.StorageFramework.Provider.ProviderTest";
3523 char const DEMO_PROVIDER_SERVICE[] = TEST_BIN_DIR "/../demo/provider_test/provider-test";
3524 }
3525@@ -38,6 +42,11 @@
3526 ACCOUNTS_BUS_NAME, QDBusConnection::SessionBus,
3527 FAKE_ACCOUNTS_SERVICE, {}));
3528 runner_->registerService(accounts_service_);
3529+
3530+ registry_service_.reset(new QtDBusTest::QProcessDBusService(
3531+ unity::storage::registry::BUS_NAME, QDBusConnection::SessionBus,
3532+ REGISTRY_SERVICE, {}));
3533+ runner_->registerService(registry_service_);
3534 }
3535
3536 DBusEnvironment::~DBusEnvironment()
3537
3538=== modified file 'tests/utils/DBusEnvironment.h'
3539--- tests/utils/DBusEnvironment.h 2016-08-04 10:12:01 +0000
3540+++ tests/utils/DBusEnvironment.h 2016-12-12 02:53:43 +0000
3541@@ -45,5 +45,6 @@
3542 private:
3543 std::unique_ptr<QtDBusTest::DBusTestRunner> runner_;
3544 QSharedPointer<QtDBusTest::QProcessDBusService> accounts_service_;
3545+ QSharedPointer<QtDBusTest::QProcessDBusService> registry_service_;
3546 QSharedPointer<QtDBusTest::QProcessDBusService> demo_provider_;
3547 };
3548
3549=== modified file 'tests/utils/ProviderFixture.h'
3550--- tests/utils/ProviderFixture.h 2016-09-26 02:37:03 +0000
3551+++ tests/utils/ProviderFixture.h 2016-12-12 02:53:43 +0000
3552@@ -23,7 +23,11 @@
3553 #include <utils/DBusEnvironment.h>
3554 #include <utils/ProviderClient.h>
3555
3556+#pragma GCC diagnostic push
3557+#pragma GCC diagnostic ignored "-Wctor-dtor-privacy"
3558 #include <gtest/gtest.h>
3559+#pragma GCC diagnostic pop
3560+
3561 #include <OnlineAccounts/Account>
3562 #include <OnlineAccounts/Manager>
3563 #include <QDBusConnection>
3564
3565=== removed file 'tests/utils/com.ubuntu.OnlineAccounts.Manager.xml'
3566--- tests/utils/com.ubuntu.OnlineAccounts.Manager.xml 2016-07-12 02:25:26 +0000
3567+++ tests/utils/com.ubuntu.OnlineAccounts.Manager.xml 1970-01-01 00:00:00 +0000
3568@@ -1,153 +0,0 @@
3569-<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
3570-"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
3571-
3572-<node name="/com/ubuntu/OnlineAccounts/Manager">
3573- <interface name="com.ubuntu.OnlineAccounts.Manager">
3574-
3575- <!--
3576- Global concepts:
3577-
3578- Clients are identified by their "applicationId", which is the
3579- "<package>_<app>" of the client.
3580-
3581- The "serviceId" is an application-specific name for an account provider.
3582- That is, the "serviceId" contains the information about the application
3583- which will use it, and the account provider (e.g. "google", "facebook").
3584- "serviceId"s are backed by files shipped with the application, which can
3585- contain application/account-provider specific information, such as the
3586- ClientId and ClientSecret to be used when authentication with OAuth 2.0.
3587- An application can ship more than one "serviceId", if they refer to
3588- different account providers; that is, one application can have a
3589- serviceId for Google and one for Facebook, but the same application
3590- cannot have one for GMail and another for Picasa.
3591- -->
3592-
3593- <!--
3594- GetAccounts: returns a list of account IDs that satisfy the given
3595- filters.
3596-
3597- Allowed keys for the "filters" parameter (any combination is allowed,
3598- though not all combinations might make sense):
3599-
3600- - "applicationId" ("s"): the "<package>_<app>" of the client. An
3601- unconfined application can specify this in order to restrict the set
3602- of results to only those accounts that the application has been
3603- authorized to use. For confined apps, OA will deduce the
3604- applicationId from the apparmor label of the caller.
3605-
3606- - "serviceId" ("s"): if the application wants to list only those
3607- accounts coming from a specific provider (e.g., "Facebook").
3608-
3609- - "accountId" ("u"): the ID of an account.
3610-
3611- In any case, an application will receive only those accounts which the
3612- user has authorized the application to use. See
3613- http://wiki.ubuntu.com/OnlineAccounts
3614- for an overview of the UI experience.
3615-
3616- Disabled accounts will not be returned.
3617- -->
3618- <method name="GetAccounts">
3619- <arg name="filters" type="a{sv}" direction="in" />
3620- <!--
3621- The return value is a list of account IDs paired with a dictionary of account data.
3622- This will always include:
3623- - "serviceId" (s)
3624- - "displayName" (s)
3625- Other settings stored on the account will also be included, such as the
3626- server address and port of an owncloud or IMAP account, but we haven't
3627- defined exactly how. Possibly, all account-specific keys will be
3628- prefixed by "settings/", in order not to clash with the keys defined at
3629- the framework level.
3630- -->
3631- <arg name="accounts" type="a(ua{sv})" direction="out" />
3632- <annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
3633- <annotation name="org.qtproject.QtDBus.QtTypeName.Out0"
3634- value="QList&lt;AccountInfo&gt;"/>
3635- </method>
3636-
3637- <!--
3638- Authenticate: request authentication credentials for the given
3639- account ID in the context of a particular service.
3640-
3641- If "interactive" is false, an error will be returned if
3642- user interaction would be required to retrieve the
3643- credentials.
3644-
3645- If "invalidate" is true, any stored credentials will be
3646- ignored and new credentials will be requested from the account
3647- provider.
3648- -->
3649- <method name="Authenticate">
3650- <arg name="accountId" type="u" direction="in" />
3651- <arg name="serviceId" type="s" direction="in" />
3652- <arg name="interactive" type="b" direction="in" />
3653- <arg name="invalidate" type="b" direction="in" />
3654- <!--
3655- This dictionary can be used to specify OAuth client keys or permission
3656- scopes. While it's possible to statically define them a the "serviceId"
3657- level, some apps might want to change this information at runtime.
3658- Possible use cases:
3659- 1) OAuth keys are retrieved from a server (so that they can be updated
3660- when the old ones are revoked).
3661- 2) An app might want to use different keys when talking to GMail and
3662- Picasa.
3663- 3) The scope list can also be dynamic, and depending on how the user is
3664- using the app.
3665- 4) SASL: the parameters would contain the latest challenge got from the
3666- server.
3667- -->
3668- <arg name="parameters" type="a{sv}" direction="in" />
3669- <arg name="credentials" type="a{sv}" direction="out" />
3670- <annotation name="org.qtproject.QtDBus.QtTypeName.In4" value="QVariantMap"/>
3671- <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QVariantMap"/>
3672- </method>
3673-
3674- <!--
3675- RequestAccess: register a new account for use with the given
3676- service.
3677- This method also performs the authentication, since that's what apps
3678- would do as soon as they get the account.
3679- -->
3680- <method name="RequestAccess">
3681- <arg name="serviceId" type="s" direction="in" />
3682- <arg name="parameters" type="a{sv}" direction="in" />
3683- <arg name="account" type="(ua{sv})" direction="out" />
3684- <arg name="credentials" type="a{sv}" direction="out" />
3685- <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="QVariantMap"/>
3686- <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="AccountInfo"/>
3687- <annotation name="org.qtproject.QtDBus.QtTypeName.Out1" value="QVariantMap"/>
3688- </method>
3689-
3690- <!--
3691- AccountChanged: emitted when account details are changed.
3692-
3693- The apparmor policy will NOT ALLOW confined applications to receive
3694- this signal on the account manager object path (which might be
3695- /com/ubuntu/OnlineAccounts/Manager). Only unconfined applications will
3696- be able to listen to this signal from that object path.
3697-
3698- Confined apps will have to catch this signal from a different object path:
3699- /com/ubuntu/OnlineAccounts/Manager/@{APP_PKGNAME_DBUS}, which will
3700- deliver the signal only for those accounts which the app has been
3701- authorized to use.
3702- -->
3703- <signal name="AccountChanged">
3704- <!--
3705- The serviceId will also be included in the "account" dictionary. The
3706- reason for having it also here is to allow clients to filter D-Bus
3707- messages by arg0. This can be important for unconfined clients, which
3708- would otherwise be woken up by any account change, even those not
3709- relevant to them.
3710- -->
3711- <arg name="serviceId" type="s" />
3712- <!--
3713- The dictionary contains a changeType key, type "u", whose value is
3714- enum { enabled, disabled, changed }
3715- -->
3716- <arg name="account" type="(ua{sv})" />
3717- <annotation name="org.qtproject.QtDBus.QtTypeName.In1" value="AccountInfo"/>
3718- </signal>
3719-
3720- </interface>
3721-</node>
3722
3723=== modified file 'tests/utils/fake-online-accounts-daemon.py'
3724--- tests/utils/fake-online-accounts-daemon.py 2016-11-01 03:36:29 +0000
3725+++ tests/utils/fake-online-accounts-daemon.py 2016-12-12 02:53:43 +0000
3726@@ -17,7 +17,6 @@
3727
3728 """A fake version of the OnlineAccounts D-Bus service."""
3729
3730-import os
3731 import sys
3732
3733 import dbus.service
3734@@ -28,9 +27,6 @@
3735 OBJECT_PATH = "/com/ubuntu/OnlineAccounts/Manager"
3736 OA_IFACE = "com.ubuntu.OnlineAccounts.Manager"
3737
3738-INTERFACE_XML = os.path.join(os.path.dirname(__file__),
3739- "com.ubuntu.OnlineAccounts.Manager.xml")
3740-
3741 AUTH_OAUTH1 = 1
3742 AUTH_OAUTH2 = 2
3743 AUTH_PASSWORD = 3
3744@@ -90,16 +86,16 @@
3745 }, signature="sv")
3746
3747 class Account:
3748- def __init__(self, account_id, display_name, service_id, credentials, settings=None):
3749+ def __init__(self, account_id, name, service_id, credentials, settings=None):
3750 self.account_id = account_id
3751- self.display_name = display_name
3752+ self.name = name
3753 self.service_id = service_id
3754 self.credentials = credentials
3755 self.settings = settings
3756
3757 def serialise(self):
3758 account_info = dbus.Dictionary({
3759- "displayName": dbus.String(self.display_name),
3760+ "displayName": dbus.String(self.name),
3761 "serviceId": dbus.String(self.service_id),
3762 "authMethod": dbus.Int32(self.credentials.method),
3763 }, signature="sv")
3764@@ -114,12 +110,12 @@
3765 self.accounts = accounts
3766
3767 @dbus.service.method(dbus_interface=OA_IFACE,
3768- in_signature="a{sv}", out_signature="a(ua{sv})")
3769+ in_signature="a{sv}", out_signature="a(ua{sv})aa{sv}")
3770 def GetAccounts(self, filters):
3771 #print("GetAccounts %r" % filters)
3772 sys.stdout.flush()
3773 return dbus.Array([a.serialise() for a in self.accounts],
3774- signature="a(ua{sv})")
3775+ signature="a(ua{sv})"), dbus.Array(signature="a{sv}")
3776
3777 @dbus.service.method(dbus_interface=OA_IFACE,
3778 in_signature="usbba{sv}", out_signature="a{sv}")
3779@@ -178,8 +174,8 @@
3780 Account(4, "Password host account", "password-host-service",
3781 Password_Bug1628473("joe", "secret"),
3782 {"host": "http://www.example.com/"}),
3783- Account(42, "Fake google account", "google-drive-scope",
3784- OAuth2("fake-google-access-token", 0, [])),
3785+ Account(42, "Fake test account", "storage-provider-test",
3786+ OAuth2("fake-test-access-token", 0, [])),
3787 Account(99, "Fake mcloud account", "com.canonical.scopes.mcloud_mcloud_mcloud",
3788 OAuth2("fake-mcloud-access-token", 0, [])),
3789 ]

Subscribers

People subscribed via source and target branches

to all changes: