Merge lp:~gary-wzl77/storage-provider-onedrive/upload into lp:storage-provider-onedrive/devel

Proposed by Gary.Wang
Status: Merged
Merged at revision: 3
Proposed branch: lp:~gary-wzl77/storage-provider-onedrive/upload
Merge into: lp:storage-provider-onedrive/devel
Diff against target: 7075 lines (+6584/-27)
78 files modified
.bzr-builddeb/default.conf (+2/-0)
CMakeLists.txt (+8/-7)
data/CMakeLists.txt (+2/-2)
data/onedrive-provider.pc.in (+10/-0)
data/onedrive.pc.in (+0/-10)
debian/control (+2/-1)
debian/onedrive-provider0.install (+0/-2)
doc/Doxyfile.in (+2/-2)
include/onedrive/api/client.h (+203/-0)
include/onedrive/api/cloudfolder.h (+111/-0)
include/onedrive/api/clouditem.h (+123/-0)
include/onedrive/api/cloudresource.h (+69/-0)
include/onedrive/api/downloadtask.h (+119/-0)
include/onedrive/api/exceptions.h (+87/-0)
include/onedrive/api/storageinfo.h (+74/-0)
include/onedrive/api/syncmanager.h (+171/-0)
include/onedrive/api/task.h (+119/-0)
include/onedrive/api/taskqueue.h (+131/-0)
include/onedrive/api/uploadtask.h (+176/-0)
include/onedrive/api/visibility.h (+30/-0)
provider/CMakeLists.txt (+32/-0)
provider/OnedriveProvider.cpp (+634/-0)
provider/OnedriveProvider.h (+74/-0)
provider/com.canonical.StorageFramework.Provider.OnedriveProvider.service (+3/-0)
src/CMakeLists.txt (+46/-3)
src/onedrive/api/client.cpp (+106/-0)
src/onedrive/api/client_priv.cpp (+780/-0)
src/onedrive/api/client_priv.h (+106/-0)
src/onedrive/api/cloudfolder.cpp (+121/-0)
src/onedrive/api/clouditem.cpp (+166/-0)
src/onedrive/api/config.h (+55/-0)
src/onedrive/api/downloadtask.cpp (+65/-0)
src/onedrive/api/downloadtask_priv.cpp (+193/-0)
src/onedrive/api/downloadtask_priv.h (+95/-0)
src/onedrive/api/storageinfo.cpp (+64/-0)
src/onedrive/api/syncmanager.cpp (+70/-0)
src/onedrive/api/syncmanager_priv.cpp (+111/-0)
src/onedrive/api/syncmanager_priv.h (+76/-0)
src/onedrive/api/syncthread.cpp (+447/-0)
src/onedrive/api/syncthread.h (+81/-0)
src/onedrive/api/taskhandler.h (+271/-0)
src/onedrive/api/uploadtask.cpp (+74/-0)
src/onedrive/api/uploadtask_priv.cpp (+208/-0)
src/onedrive/api/uploadtask_priv.h (+111/-0)
symbols.map (+15/-0)
tests/CMakeLists.txt (+8/-0)
tests/server/resources/D47F8E4CDBE19587!104.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!105_201607.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!105_Nonexists.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!139.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!140.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!151.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!152.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!156.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!888.json (+1/-0)
tests/server/resources/D47F8E4CDBE19587!999.json (+1/-0)
tests/server/resources/invalid_token.json (+1/-0)
tests/server/resources/move_D47F8E4CDBE19587!155.json (+1/-0)
tests/server/resources/move_D47F8E4CDBE19587!159.json (+1/-0)
tests/server/resources/move_empty.json (+1/-0)
tests/server/resources/name_conflict_fail.json (+1/-0)
tests/server/resources/name_conflict_rename.json (+1/-0)
tests/server/resources/new_folder_D47F8E4CDBE19587!103.json (+1/-0)
tests/server/resources/new_folder_invalid_folder_id.json (+1/-0)
tests/server/resources/rm_generate_files.sh (+2/-0)
tests/server/resources/root.json (+1/-0)
tests/server/resources/root_Getting.json (+1/-0)
tests/server/resources/root_children.json (+1/-0)
tests/server/resources/storage_info.json (+1/-0)
tests/server/resources/update_D47F8E4CDBE19587!160.json (+1/-0)
tests/server/resources/update_D47F8E4CDBE19587!161.json (+1/-0)
tests/server/resources/update_empty.json (+1/-0)
tests/server/resources/upload_template.json (+1/-0)
tests/server/server.py (+224/-0)
tests/unit/CMakeLists.txt (+9/-0)
tests/unit/onedrive/CMakeLists.txt (+30/-0)
tests/unit/onedrive/api/onedrive-rest-test.cpp (+328/-0)
tests/unit/onedrive/api/onedrive-sync-test.cpp (+514/-0)
To merge this branch: bzr merge lp:~gary-wzl77/storage-provider-onedrive/upload
Reviewer Review Type Date Requested Status
unity-api-1-bot continuous-integration Approve
onedrive-team Pending
Review via email: mp+307157@code.launchpad.net

Commit message

Simple upload done. Support to upload content less than 100mb.

Description of the change

Simple upload done. Support to upload content less than 100mb.

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

debian file fixes.

11. By Gary.Wang

merge from devel and resolve the conflict.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :
review: Needs Fixing (continuous-integration)
12. By Gary.Wang

support split mode for builddeb.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:12
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/4/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/822/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/829
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/632/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/632/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/4/rebuild

review: Needs Fixing (continuous-integration)
13. By Gary.Wang

add cmake-extras package.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:13
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/5/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/823/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/830
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/633/console
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/633/console

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/5/rebuild

review: Needs Fixing (continuous-integration)
14. By Gary.Wang

some changes to make CI feels good.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

FAILED: Continuous integration, rev:14
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/6/
Executed test runs:
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build/824/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/831
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/634/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/634/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/634/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/634/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/634/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/634/artifact/output/*zip*/output.zip
    FAILURE: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/634/console
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/634/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/634
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/634/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/6/rebuild

review: Needs Fixing (continuous-integration)
15. By Gary.Wang

remove http::header from async_get as it's not used anymore.

Revision history for this message
unity-api-1-bot (unity-api-1-bot) wrote :

PASSED: Continuous integration, rev:15
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/7/
Executed test runs:
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build/825
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-0-fetch/832
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=vivid+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=xenial+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=amd64,release=yakkety/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=vivid+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=xenial+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=armhf,release=yakkety/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=vivid+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=xenial+overlay/635/artifact/output/*zip*/output.zip
    SUCCESS: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/635
        deb: https://jenkins.canonical.com/unity-api-1/job/build-2-binpkg/arch=i386,release=yakkety/635/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://jenkins.canonical.com/unity-api-1/job/lp-storage-provider-onedrive-ci/7/rebuild

review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory '.bzr-builddeb'
2=== added file '.bzr-builddeb/default.conf'
3--- .bzr-builddeb/default.conf 1970-01-01 00:00:00 +0000
4+++ .bzr-builddeb/default.conf 2016-09-30 08:26:58 +0000
5@@ -0,0 +1,2 @@
6+[BUILDDEB]
7+split = True
8
9=== modified file 'CMakeLists.txt'
10--- CMakeLists.txt 2016-09-26 04:27:03 +0000
11+++ CMakeLists.txt 2016-09-30 08:26:58 +0000
12@@ -16,7 +16,7 @@
13
14 cmake_minimum_required(VERSION 2.8)
15
16-project(onedrive)
17+project(onedrive-provider)
18
19 include(GNUInstallDirs)
20
21@@ -26,9 +26,9 @@
22 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Werror -Wall -fno-strict-aliasing -fvisibility=hidden -fvisibility-inlines-hidden -pedantic -Wextra")
23 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined")
24
25-set(ONEDRIVE_LIB_VERSION_MAJOR 0)
26-set(ONEDRIVE_LIB_VERSION_MINOR 0)
27-set(ONEDRIVE_LIB_VERSION_PATCH 1)
28+set(ONEDRIVE_PROVIDER_LIB_VERSION_MAJOR 0)
29+set(ONEDRIVE_PROVIDER_LIB_VERSION_MINOR 0)
30+set(ONEDRIVE_PROVIDER_LIB_VERSION_PATCH 1)
31
32 include(CTest)
33
34@@ -36,7 +36,7 @@
35 include/
36 )
37
38-file(GLOB_RECURSE ONEDRIVE_LIB_INTERFACE_HEADERS include/*.h)
39+file(GLOB_RECURSE ONEDRIVE_PROVIDER_LIB_INTERFACE_HEADERS include/*.h)
40
41 include(EnableCoverageReport)
42
43@@ -45,11 +45,12 @@
44 add_subdirectory(include)
45 add_subdirectory(src)
46 add_subdirectory(tests)
47-add_subdirectory(provider)
48+#add_subdirectory(provider)
49
50 enable_coverage_report(
51 TARGETS
52- onedrive
53+ onedrive-provider
54+ #onedrive-provider-bin
55 FILTER
56 ${CMAKE_SOURCE_DIR}/test/*
57 ${CMAKE_BINARY_DIR}/*
58
59=== modified file 'data/CMakeLists.txt'
60--- data/CMakeLists.txt 2016-09-26 04:27:03 +0000
61+++ data/CMakeLists.txt 2016-09-30 08:26:58 +0000
62@@ -15,10 +15,10 @@
63 # Authored by: Gary Wang <gary.wang@canonical.com>
64
65 configure_file(
66- onedrive.pc.in onedrive.pc @ONLY
67+ onedrive-provider.pc.in onedrive-provider.pc @ONLY
68 )
69
70 install(
71- FILES ${CMAKE_CURRENT_BINARY_DIR}/onedrive.pc
72+ FILES ${CMAKE_CURRENT_BINARY_DIR}/onedrive-provider.pc
73 DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig
74 )
75
76=== added file 'data/onedrive-provider.pc.in'
77--- data/onedrive-provider.pc.in 1970-01-01 00:00:00 +0000
78+++ data/onedrive-provider.pc.in 2016-09-30 08:26:58 +0000
79@@ -0,0 +1,10 @@
80+prefix=@CMAKE_INSTALL_PREFIX@
81+exec_prefix=${prefix}
82+libdir=${exec_prefix}/lib
83+includedir=${exec_prefix}/include
84+
85+Name: @CMAKE_PROJECT_NAME@
86+Description: Cloud based content sharing library for Microsoft Onedrive service
87+Version: @ONEDRIVE_LIB_VERSION_MAJOR@.@ONEDRIVE_LIB_VERSION_MINOR@.@ONEDRIVE_LIB_VERSION_PATCH@
88+Libs: -L${libdir} -lonedrive
89+Cflags: -I${includedir}
90
91=== removed file 'data/onedrive.pc.in'
92--- data/onedrive.pc.in 2016-09-26 04:27:03 +0000
93+++ data/onedrive.pc.in 1970-01-01 00:00:00 +0000
94@@ -1,10 +0,0 @@
95-prefix=@CMAKE_INSTALL_PREFIX@
96-exec_prefix=${prefix}
97-libdir=${exec_prefix}/lib
98-includedir=${exec_prefix}/include
99-
100-Name: @CMAKE_PROJECT_NAME@
101-Description: Cloud based content sharing library for Microsoft Onedrive service
102-Version: @ONEDRIVE_LIB_VERSION_MAJOR@.@ONEDRIVE_LIB_VERSION_MINOR@.@ONEDRIVE_LIB_VERSION_PATCH@
103-Libs: -L${libdir} -lonedrive
104-Cflags: -I${includedir}
105
106=== modified file 'debian/control'
107--- debian/control 2016-09-30 05:26:58 +0000
108+++ debian/control 2016-09-30 08:26:58 +0000
109@@ -2,11 +2,12 @@
110 Priority: optional
111 Maintainer: Gary Wang <gary.wang@canonical.com>
112 Build-Depends: cmake,
113+ cmake-extras (>= 0.4),
114 debhelper (>= 9),
115 doxygen,
116 google-mock,
117 graphviz,
118- libnet-cpp-dev,
119+ libnet-cpp-dev (>= 2.0.0),
120 libboost-dev (>= 1.58) | libboost1.58-dev,
121 libboost-filesystem-dev (>= 1.58) | libboost-filesystem1.58-dev,
122 libboost-system-dev (>= 1.58) | libboost-system1.58-dev,
123
124=== modified file 'debian/onedrive-provider0.install'
125--- debian/onedrive-provider0.install 2016-09-30 05:26:58 +0000
126+++ debian/onedrive-provider0.install 2016-09-30 08:26:58 +0000
127@@ -1,3 +1,1 @@
128 usr/lib/*/lib*.so.*
129-usr/bin/*
130-usr/share/dbus-1/services/*
131
132=== modified file 'doc/Doxyfile.in'
133--- doc/Doxyfile.in 2016-09-26 04:27:03 +0000
134+++ doc/Doxyfile.in 2016-09-30 08:26:58 +0000
135@@ -32,13 +32,13 @@
136 # This could be handy for archiving the generated documentation or
137 # if some version control system is used.
138
139-PROJECT_NUMBER = @ONEDIRVE_LIB_VERSION_MAJOR@.@ONEDIRVE_LIB_VERSION_MINOR@.@ONEDIRVE_LIB_VERSION_PATCH@
140+PROJECT_NUMBER = @ONEDIRVE_PROVIDER_LIB_VERSION_MAJOR@.@ONEDIRVE_PROVIDER_LIB_VERSION_MINOR@.@ONEDIRVE_PROVIDER_LIB_VERSION_PATCH@
141
142 # Using the PROJECT_BRIEF tag one can provide an optional one line description
143 # for a project that appears at the top of each page and should give viewer
144 # a quick idea about the purpose of the project. Keep the description short.
145
146-PROJECT_BRIEF = "Onedrive API library For Microsoft OneDrive Service"
147+PROJECT_BRIEF = "Onedrive API library For Microsoft OneDrive Service and a Storage Provider."
148
149 # With the PROJECT_LOGO tag one can specify an logo or icon that is
150 # included in the documentation. The maximum height of the logo should not
151
152=== added file 'include/onedrive/api/client.h'
153--- include/onedrive/api/client.h 1970-01-01 00:00:00 +0000
154+++ include/onedrive/api/client.h 2016-09-30 08:26:58 +0000
155@@ -0,0 +1,203 @@
156+/*
157+ * Copyright © 2016 Canonical Ltd.
158+ *
159+ * This program is free software: you can redistribute it and/or modify it
160+ * under the terms of the GNU Lesser General Public License version 3,
161+ * as published by the Free Software Foundation.
162+ *
163+ * This program is distributed in the hope that it will be useful,
164+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
165+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
166+ * GNU Lesser General Public License for more details.
167+ *
168+ * You should have received a copy of the GNU Lesser General Public License
169+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
170+ *
171+ * Authored by: Gary Wang <gary.wang@canonical.com>
172+ */
173+
174+#ifndef ONEDRIVE_API_CLIENT_H_
175+#define ONEDRIVE_API_CLIENT_H_
176+
177+#include <onedrive/api/visibility.h>
178+#include <onedrive/api/taskqueue.h>
179+#include <onedrive/api/storageinfo.h>
180+#include <onedrive/api/cloudresource.h>
181+#include <onedrive/api/clouditem.h>
182+#include <onedrive/api/cloudfolder.h>
183+#include <onedrive/api/downloadtask.h>
184+#include <onedrive/api/uploadtask.h>
185+#include <onedrive/api/syncmanager.h>
186+
187+#include <deque>
188+
189+namespace onedrive {
190+namespace api {
191+
192+class ClientPriv;
193+
194+/*!
195+ \class Client
196+ \brief Onedrive API provides developer to easily access login user's cloud contents stored on microsoft onedrive service,
197+ such as musics, movie, docs, images, and so on.
198+
199+ The API enable developers to
200+ <list type="bullet">
201+ <item>retrieve authorized user cloud content list.</item>
202+ <item>create, delete, move and update cloud resources.</item>
203+ <item>query content infomation.</item>
204+ <item>create an extranet link to share.</item>
205+ <item>upload a local content to onedrive.</item>
206+ <item>download a content from onedrive.</item>
207+ </list>
208+
209+ Also sync up manager will be running on the background when client is constructed. It handles over
210+ local content upload and cloud item download. \sa syncmanager.
211+
212+ \note Onedrive API covers cloud resourece access and content sync-up between local and cloud. It does not take
213+ responsibility of account authentication. So before using onedrive APIs, developers need to call \sa set_access_token to
214+ manually set a valid access_token or \sa refresh_token to fetch access token,
215+ which is used to call onedrive APIs internally to pass through authentication.
216+ */
217+
218+class ONEDRIVE_API_DLL_PUBLIC Client {
219+
220+ public:
221+ typedef std::shared_ptr<Client> Ptr;
222+
223+ typedef std::deque<CloudResource::Ptr> ResourceList;
224+
225+ typedef std::vector<std::string> Stringlist;
226+
227+ /*!
228+ * \brief Constructs a onedrive Client object with \a request_timeout seconds.
229+ * Meanwhile client launches sync-up manager to deal with task download and upload by default.
230+ */
231+ Client(int request_timeout = 10);
232+
233+ Client(const Client&) = delete;
234+
235+ Client& operator=(const Client&) = delete;
236+
237+ virtual ~Client();
238+
239+ /*!
240+ * \brief Set \a access_token to authenticate all onedrive API calls with the bearer HTTP authorization scheme.
241+ * The access token can be fetched through ubuntu sso services.
242+ */
243+ void set_access_token(const std::string &access_token);
244+
245+ /*!
246+ * \brief Retrieves and refreshes access token by using \a refresh_token.
247+ * The refresh token can be fetched through ubuntu sso services.
248+ * \throw std::runtime_error if error occurs.
249+ * \returns true if access token is refreshed, otherwise returns false.
250+ */
251+// bool refresh_token(const std::string &refresh_token);
252+
253+ /*!
254+ * \brief Returns login user's onedrive cloud storage information.
255+ * \throw std::runtime_error if error occurs.
256+ * @sa UserInfo
257+ */
258+ StorageInfo storage_info();
259+
260+ /*!
261+ * \brief Returns root folder object on onedrive.
262+ * \throw std::runtime_error if error occurs.
263+ * \sa cloud_content_list(), storage_info()
264+ */
265+ CloudFolder::Ptr root_folder();
266+
267+ /*!
268+ * \brief Returns cloud item list and next page token when querying one specific folder \a folder_id.
269+ * if \a folder_id is empty, returns item list under root directory of onedrive.
270+ * if \a page_token is empty, queries contents from the first page.
271+ * The fetched content count is 200 at most per call.
272+ * \a page_token indicates the specific page index on the onedrive.
273+ * \throw std::runtime_error if error occurs.
274+ * \sa root_folder(), metadata(), search()
275+ */
276+ std::tuple<ResourceList, std::string> cloud_content_list(const std::string &folder_id = std::string(),
277+ const std::string &page_token = std::string());
278+
279+ /*!
280+ * \brief Returns a resouce item object if content with a given \a content_id can be found on onedrive.
281+ * otherwise return nullptr.
282+ * \throw std::runtime_error if error occurs.
283+ * \sa cloud_content_list()
284+ */
285+ CloudResource::Ptr metadata(const std::string & content_id);
286+
287+ /*!
288+ * \brief Returns a folder item object if a folder \a folder_name is created under a given \a folder_id folder,
289+ * otherwise return nullptr.
290+ * if \a folder_id is empty, creates a folder item under root folder of onedrive.
291+ * \throw std::runtime_error if error occurs.
292+ * \sa delete_item(), move_item(), copy_item()
293+ */
294+ CloudFolder::Ptr create_folder(const std::string &folder_name,
295+ const std::string &folder_id = std::string());
296+
297+ /*!
298+ * \brief Returns a cloud item list if there are available items that matches with \a name under a given \a folder_id folder.
299+ * if \a folder_id is empty, searches items under root folder of onedrive.
300+ * \throw std::runtime_error if error occurs.
301+ * \sa delete_item(), metadata()
302+ */
303+ Client::ResourceList search(const std::string &name,
304+ const std::string &folder_id = std::string());
305+
306+ /*!
307+ * \brief Returns true if content \a content_id is deleted, otherwise return false.
308+ * \throw std::runtime_error if error occurs.
309+ * \sa move_item(), metadata(), copy_item()
310+ */
311+ bool delete_item(const std::string &content_id);
312+
313+ /*!
314+ * \brief Returns a resource item object if an item \a item_id is copies to a given folder \a folder_id with a new \a name on onedrive.
315+ * otherwise return nullptr.
316+ * \throw std::runtime_error if error occurs.
317+ * \sa move_item(), update_folder(), delete_item()
318+ CloudResource::Ptr copy_item(const std::string &item_id,
319+ const std::string &name,
320+ const std::string &folder_id);
321+ */
322+
323+ /*!
324+ * \brief Returns a resource item object if an item \a item_id is moved to a given folder \a folder_id on onedrive with new \a item_name .
325+ * otherwise return nullptr.
326+ * if item_name is empty, name will not changed after moving to a new folder.
327+ * \throw std::runtime_error if error occurs.
328+ * \sa move_item(), update_folder(), delete_item()
329+ */
330+ CloudResource::Ptr move_item(const std::string &item_id,
331+ const std::string &folder_id,
332+ const std::string &item_name = std::string());
333+
334+ /*!
335+ * \brief Returns a resource item object if an item \a item_id is updated with \a new name, otherwise return false.
336+ * otherwise return nullptr.
337+ * \throw std::runtime_error if error occurs.
338+ * \sa delete_contents(), copy_folders(),
339+ */
340+ CloudResource::Ptr rename_item(const std::string &folder_id,
341+ const std::string &new_folder_name);
342+
343+
344+ /*!
345+ * \brief Returns a sync-up manager running on the background.
346+ * sync-up manager scheduled tasks \sa start, pause, cancel for content upload and download.
347+ */
348+ SyncManager::Ptr syncmanager() const;
349+
350+ private:
351+ std::shared_ptr<ClientPriv> p;
352+
353+};
354+
355+}
356+}
357+
358+#endif // ONEDRIVE_API_CLIENT_H_
359
360=== added file 'include/onedrive/api/cloudfolder.h'
361--- include/onedrive/api/cloudfolder.h 1970-01-01 00:00:00 +0000
362+++ include/onedrive/api/cloudfolder.h 2016-09-30 08:26:58 +0000
363@@ -0,0 +1,111 @@
364+/*
365+ * Copyright © 2016 Canonical Ltd.
366+ *
367+ * This program is free software: you can redistribute it and/or modify it
368+ * under the terms of the GNU Lesser General Public License version 3,
369+ * as 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+ * Authored by: Gary Wang <gary.wang@canonical.com>
380+ */
381+
382+#ifndef ONEDRIVE_API_CLOUDFOLDER_H_
383+#define ONEDRIVE_API_CLOUDFOLDER_H_
384+
385+#include <onedrive/api/cloudresource.h>
386+#include <onedrive/api/visibility.h>
387+
388+namespace Json {
389+ class Value;
390+}
391+
392+namespace onedrive {
393+namespace api {
394+
395+/*!
396+ \class CloudFolder
397+ \brief CloudFolder represents a folder object on onedrive.
398+ */
399+
400+class ONEDRIVE_API_DLL_PUBLIC CloudFolder : public CloudResource {
401+public:
402+ typedef std::shared_ptr<CloudFolder> Ptr;
403+
404+ virtual ~CloudFolder() = default;
405+
406+ /*!
407+ * \brief Returns a unique id of cloud folder object.
408+ */
409+ const std::string &id() const override;
410+
411+ /*!
412+ * \brief Returns the name of cloud folder object.
413+ */
414+ const std::string &name() const override;
415+
416+ /*!
417+ * \brief Returns the datetime when folder was created.
418+ */
419+ const std::time_t &created_date() const override;
420+
421+ /*!
422+ * \brief Returns the datetime when folder was updated.
423+ */
424+ const std::time_t &updated_date() const override;
425+
426+ /*!
427+ * \brief Returns a shared link on onedriver for a folder .
428+ */
429+ const std::string &download_url() const override;
430+
431+ /*!
432+ * \brief Returns a unique id of the parent folder.
433+ */
434+ const std::string &folder_id() const override;
435+
436+ /*!
437+ * \brief Returns etag of a folder object.
438+ */
439+ const std::string &etag() const override;
440+
441+ /*!
442+ * \brief Returns owner id of a folder object.
443+ */
444+ const std::string &owner() const override;
445+
446+ /*!
447+ * \brief Returns resource property of an object.
448+ * \sa CloudResource::Property
449+ */
450+ CloudResource::Property property() const override;
451+
452+ /*!
453+ * \brief Returns a item' parent folder path on onedrive.
454+ */
455+ const std::string &folder_path() const override;
456+
457+ /*!
458+ * \brief Returns the number of children items under this folder.
459+ */
460+ int children_count() const;
461+
462+private:
463+ CloudFolder(const Json::Value &root);
464+
465+ friend class ClientPriv;
466+
467+ class Priv;
468+ std::shared_ptr<Priv> p;
469+};
470+
471+}
472+}
473+
474+#endif // ONEDRIVE_API_CLOUDFOLDER_H_
475
476=== added file 'include/onedrive/api/clouditem.h'
477--- include/onedrive/api/clouditem.h 1970-01-01 00:00:00 +0000
478+++ include/onedrive/api/clouditem.h 2016-09-30 08:26:58 +0000
479@@ -0,0 +1,123 @@
480+/*
481+ * Copyright © 2016 Canonical Ltd.
482+ *
483+ * This program is free software: you can redistribute it and/or modify it
484+ * under the terms of the GNU Lesser General Public License version 3,
485+ * as published by the Free Software Foundation.
486+ *
487+ * This program is distributed in the hope that it will be useful,
488+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
489+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
490+ * GNU Lesser General Public License for more details.
491+ *
492+ * You should have received a copy of the GNU Lesser General Public License
493+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
494+ *
495+ * Authored by: Gary Wang <gary.wang@canonical.com>
496+ */
497+
498+#ifndef ONEDRIVE_API_CloudItem_H_
499+#define ONEDRIVE_API_CloudItem_H_
500+
501+#include <onedrive/api/cloudresource.h>
502+#include <onedrive/api/visibility.h>
503+
504+#include <unordered_map>
505+
506+namespace Json {
507+ class Value;
508+}
509+
510+namespace onedrive {
511+namespace api {
512+
513+/*!
514+ \class CloudItem
515+ \brief CloudItem represents a item object on onedrive.
516+ */
517+
518+class ONEDRIVE_API_DLL_PUBLIC CloudItem: public CloudResource {
519+public:
520+ typedef std::shared_ptr<CloudItem> Ptr;
521+
522+ virtual ~CloudItem() = default;
523+
524+ /*!
525+ * \brief Returns a unique id of cloud item object.
526+ */
527+ const std::string &id() const override;
528+
529+ /*!
530+ * \brief Returns the name of cloud item object.
531+ */
532+ const std::string &name() const override;
533+
534+ /*!
535+ * \brief Returns the datetime when item was created.
536+ */
537+ const std::time_t &created_date() const override;
538+
539+ /*!
540+ * \brief Returns the datetime when item was updated.
541+ */
542+ const std::time_t &updated_date() const override;
543+
544+ /*!
545+ * \brief Returns a download link on onedriver for a item .
546+ */
547+ const std::string &download_url() const override;
548+
549+ /*!
550+ * \brief Returns a item' parent folder id on onedrive.
551+ */
552+ const std::string &folder_id() const override;
553+
554+ /*!
555+ * \brief Returns a item' parent folder path on onedrive.
556+ */
557+ const std::string &folder_path() const override;
558+
559+ /*!
560+ * \brief Returns etag of a item object.
561+ */
562+ const std::string &etag() const override;
563+
564+ /*!
565+ * \brief Returns owner id of a item object.
566+ */
567+ const std::string &owner() const override;
568+
569+ /*!
570+ * \brief Returns resource type of an object.
571+ */
572+ CloudResource::Property property() const override;
573+
574+ /*!
575+ * \brief Returns content size of an object in bytes.
576+ */
577+ int64_t size() const;
578+
579+ /*!
580+ * \brief Returns item's mimetype.
581+ */
582+ const std::string &mimetype() const;
583+
584+ /*!
585+ * \brief content specific metadata info.
586+ */
587+ std::unordered_map<std::string, std::string> &metadata() const;
588+
589+private:
590+ CloudItem(const Json::Value &root);
591+
592+ friend class UploadTaskPriv;
593+ friend class ClientPriv;
594+
595+ class Priv;
596+ std::shared_ptr<Priv> p;
597+};
598+
599+}
600+}
601+
602+#endif // ONEDRIVE_API_CloudItem_H_
603
604=== added file 'include/onedrive/api/cloudresource.h'
605--- include/onedrive/api/cloudresource.h 1970-01-01 00:00:00 +0000
606+++ include/onedrive/api/cloudresource.h 2016-09-30 08:26:58 +0000
607@@ -0,0 +1,69 @@
608+/*
609+ * Copyright © 2016 Canonical Ltd.
610+ *
611+ * This program is free software: you can redistribute it and/or modify it
612+ * under the terms of the GNU Lesser General Public License version 3,
613+ * as published by the Free Software Foundation.
614+ *
615+ * This program is distributed in the hope that it will be useful,
616+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
617+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
618+ * GNU Lesser General Public License for more details.
619+ *
620+ * You should have received a copy of the GNU Lesser General Public License
621+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
622+ *
623+ * Authored by: Gary Wang <gary.wang@canonical.com>
624+ */
625+
626+#ifndef ONEDRIVE_API_CLOUDRESOURCE_H_
627+#define ONEDRIVE_API_CLOUDRESOURCE_H_
628+
629+#include <memory>
630+#include <string>
631+#include <ctime>
632+
633+namespace onedrive {
634+namespace api {
635+
636+/*!
637+ \class CloudResource
638+ \brief CloudResource is an abstract object that provides common interfaces for CloudItem and CloudFolder.
639+ */
640+
641+class CloudResource {
642+ public:
643+ typedef std::shared_ptr<CloudResource> Ptr;
644+
645+ enum class Property {
646+ Content, ///< content resource
647+ Folder ///< folder resource
648+ };
649+
650+ virtual ~CloudResource() = default;
651+
652+ virtual const std::string &id() const = 0;
653+
654+ virtual const std::string &name() const = 0;
655+
656+ virtual const std::time_t &created_date() const = 0;
657+
658+ virtual const std::time_t &updated_date() const = 0;
659+
660+ virtual const std::string &download_url() const = 0;
661+
662+ virtual const std::string &folder_id() const = 0;
663+
664+ virtual const std::string &folder_path() const = 0;
665+
666+ virtual const std::string &etag() const = 0;
667+
668+ virtual const std::string &owner() const = 0;
669+
670+ virtual Property property() const = 0;
671+};
672+
673+}
674+}
675+
676+#endif // ONEDRIVE_API_CLOUDRESOURCE_H_
677
678=== added file 'include/onedrive/api/downloadtask.h'
679--- include/onedrive/api/downloadtask.h 1970-01-01 00:00:00 +0000
680+++ include/onedrive/api/downloadtask.h 2016-09-30 08:26:58 +0000
681@@ -0,0 +1,119 @@
682+/*
683+ * Copyright © 2016 Canonical Ltd.
684+ *
685+ * This program is free software: you can redistribute it and/or modify it
686+ * under the terms of the GNU Lesser General Public License version 3,
687+ * as published by the Free Software Foundation.
688+ *
689+ * This program is distributed in the hope that it will be useful,
690+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
691+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
692+ * GNU Lesser General Public License for more details.
693+ *
694+ * You should have received a copy of the GNU Lesser General Public License
695+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
696+ *
697+ * Authored by: Gary Wang <gary.wang@canonical.com>
698+ */
699+
700+#ifndef ONEDRIVE_API_DOWNLOADTASK_H_
701+#define ONEDRIVE_API_DOWNLOADTASK_H_
702+
703+#include <onedrive/api/visibility.h>
704+#include <onedrive/api/cloudresource.h>
705+#include <onedrive/api/task.h>
706+
707+namespace onedrive {
708+namespace api {
709+
710+class TaskHandler;
711+
712+/*!
713+ \struct DownloadBufferCb
714+ \brief DownloadBufferCb is a download request object which consists of a content id and
715+ writing callback function allows content data can be received in buffering via callback function.
716+ */
717+struct ONEDRIVE_API_DLL_PUBLIC DownloadBufferCb
718+{
719+ std::string content_id;
720+ Task::Buffer_Callback write_cb;
721+};
722+
723+class DownloadTaskPriv;
724+class SyncManagerPriv;
725+
726+/*!
727+ \class DownloadTask
728+ \brief DownloadTask is a task item that can be accessed from application layer to fetch
729+ basic download item information, also it's used for content download by sync manager.
730+ */
731+class ONEDRIVE_API_DLL_PUBLIC DownloadTask : public Task {
732+public:
733+ typedef std::shared_ptr<DownloadTask> Ptr;
734+
735+ virtual ~DownloadTask() = default;
736+
737+ DownloadTask& operator=(const DownloadTask& ) = delete;
738+
739+ /*!
740+ * \brief Returns a display name of cloud content on onedrive.
741+ */
742+ const std::string & content_name() const override;
743+
744+ /*!
745+ * \brief Returns cloud content local storage file path.
746+ */
747+ const std::string & file_path() const override;
748+
749+ /*!
750+ * \brief Returns download url assigned by onedrive for this task.
751+ * \note this url will be expried after a period of time.
752+ */
753+ const std::string & task_url() const override;
754+
755+ /*!
756+ * \brief Contains the error code if an error occurs during content download.
757+ */
758+ const std::string & error_code() const override;
759+
760+ /*!
761+ * \brief Contains the error string if an error occurs during content download.
762+ */
763+ const std::string & error_message() const override;
764+
765+ /*!
766+ * \brief Returns current sync-up status for this task.
767+ * \sa Task::TaskStatus
768+ */
769+ Task::Status status() const override;
770+
771+ /*!
772+ * \brief Handler for download progress of a task.
773+ * \sa Task::ProgressHandler
774+ */
775+ Task::ProgressHandler & progress_changed() override;
776+
777+ /*!
778+ * \brief Handler for download status of a task.
779+ * \sa Task::StatusHandler
780+ */
781+ Task::StatusHandler & status_changed() override;
782+
783+ /*!
784+ * \brief cancel the task.
785+ * \sa Task::StatusHandler
786+ */
787+ void cancel() override;
788+
789+private:
790+ DownloadTask(std::shared_ptr<DownloadTaskPriv> p);
791+
792+ friend class SyncManagerPriv;
793+
794+ std::shared_ptr<DownloadTaskPriv> p_;
795+};
796+
797+}
798+}
799+
800+#endif // ONEDRIVE_API_DOWNLOADTASK_H_
801
802=== added file 'include/onedrive/api/exceptions.h'
803--- include/onedrive/api/exceptions.h 1970-01-01 00:00:00 +0000
804+++ include/onedrive/api/exceptions.h 2016-09-30 08:26:58 +0000
805@@ -0,0 +1,87 @@
806+/*
807+ * Copyright © 2016 Canonical Ltd.
808+ *
809+ * This program is free software: you can redistribute it and/or modify it
810+ * under the terms of the GNU Lesser General Public License version 3,
811+ * as published by the Free Software Foundation.
812+ *
813+ * This program is distributed in the hope that it will be useful,
814+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
815+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
816+ * GNU Lesser General Public License for more details.
817+ *
818+ * You should have received a copy of the GNU Lesser General Public License
819+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
820+ *
821+ * Authored by: Gary Wang <gary.wang@canonical.com>
822+ */
823+
824+#ifndef ONEDRIVE_API_EXCEPTIONS_H_
825+#define ONEDRIVE_API_EXCEPTIONS_H_
826+
827+#include <onedrive/api/visibility.h>
828+
829+#include <exception>
830+
831+namespace onedrive {
832+namespace api {
833+
834+ /**
835+ * \brief Indicates a content or folder can not be found on onedrive.
836+ */
837+ class ONEDRIVE_API_DLL_PUBLIC NonExistentException : public std::runtime_error {
838+ public:
839+ using runtime_error::runtime_error;
840+ };
841+
842+ /**
843+ * \brief User ran out of space on onedrive storage.
844+ */
845+ class ONEDRIVE_API_DLL_PUBLIC OutofSpaceException : public std::runtime_error {
846+ public:
847+ using runtime_error::runtime_error;
848+ };
849+
850+ /**
851+ * \brief Indicates a timeout on HTTP requests.
852+ */
853+ class ONEDRIVE_API_DLL_PUBLIC HttpTimeoutException : public std::runtime_error {
854+ public:
855+ using runtime_error::runtime_error;
856+ };
857+
858+ /**
859+ * \brief Indicates one or more http request parameters are invalid.
860+ */
861+ class ONEDRIVE_API_DLL_PUBLIC ParameterInvalidException : public std::runtime_error {
862+ public:
863+ using runtime_error::runtime_error;
864+ };
865+
866+ /**
867+ * \brief Indicates access token is invalid or expired.
868+ */
869+ class ONEDRIVE_API_DLL_PUBLIC CredentialException : public std::runtime_error {
870+ public:
871+ using runtime_error::runtime_error;
872+ };
873+
874+ /**
875+ * \brief Indicates The service is not available. Try the request again after a delay.
876+ */
877+ class ONEDRIVE_API_DLL_PUBLIC ServiceNotAvailableException : public std::runtime_error {
878+ public:
879+ using runtime_error::runtime_error;
880+ };
881+
882+ /**
883+ * \brief Unknown exception.
884+ */
885+ class ONEDRIVE_API_DLL_PUBLIC UnknownException : public std::runtime_error {
886+ public:
887+ using runtime_error::runtime_error;
888+ };
889+}
890+}
891+
892+#endif // ONEDRIVE_API_EXCEPTIONS_H_
893
894=== added file 'include/onedrive/api/storageinfo.h'
895--- include/onedrive/api/storageinfo.h 1970-01-01 00:00:00 +0000
896+++ include/onedrive/api/storageinfo.h 2016-09-30 08:26:58 +0000
897@@ -0,0 +1,74 @@
898+/*
899+ * Copyright © 2016 Canonical Ltd.
900+ *
901+ * This program is free software: you can redistribute it and/or modify it
902+ * under the terms of the GNU Lesser General Public License version 3,
903+ * as published by the Free Software Foundation.
904+ *
905+ * This program is distributed in the hope that it will be useful,
906+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
907+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
908+ * GNU Lesser General Public License for more details.
909+ *
910+ * You should have received a copy of the GNU Lesser General Public License
911+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
912+ *
913+ * Authored by: Gary Wang <gary.wang@canonical.com>
914+ */
915+
916+#ifndef ONEDRIVE_API_STORAGEINFO_H_
917+#define ONEDRIVE_API_STORAGEINFO_H_
918+
919+#include <onedrive/api/visibility.h>
920+
921+#include <memory>
922+#include <string>
923+
924+namespace Json {
925+ class Value;
926+}
927+
928+namespace onedrive {
929+namespace api {
930+
931+/*!
932+ \class StorageInfo
933+ \brief StorageInfo is a class that provides basic user's account and storage usage information on onedrive.
934+ */
935+
936+class ONEDRIVE_API_DLL_PUBLIC StorageInfo {
937+public:
938+ virtual ~StorageInfo() = default;
939+
940+ /*!
941+ * \brief Returns authorized user's id.
942+ */
943+ const std::string &id() const;
944+
945+ /*!
946+ * \brief Returns authorized user's name.
947+ */
948+ const std::string &name() const;
949+
950+ /*!
951+ * \brief Returns used disk size of user cloud storage in Bytes.
952+ */
953+ int64_t used_disk_size() const;
954+
955+ /*!
956+ * \brief Returns total disk size assigned by onedrive in Bytes.
957+ */
958+ int64_t total_disk_size() const;
959+private:
960+ StorageInfo(const Json::Value &root);
961+
962+ friend class ClientPriv;
963+ class Priv;
964+
965+ std::shared_ptr<Priv> p;
966+};
967+
968+}
969+}
970+
971+#endif // ONEDRIVE_API_STORAGEINFO_H_
972
973=== added file 'include/onedrive/api/syncmanager.h'
974--- include/onedrive/api/syncmanager.h 1970-01-01 00:00:00 +0000
975+++ include/onedrive/api/syncmanager.h 2016-09-30 08:26:58 +0000
976@@ -0,0 +1,171 @@
977+/*
978+ * Copyright © 2016 Canonical Ltd.
979+ *
980+ * This program is free software: you can redistribute it and/or modify it
981+ * under the terms of the GNU Lesser General Public License version 3,
982+ * as published by the Free Software Foundation.
983+ *
984+ * This program is distributed in the hope that it will be useful,
985+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
986+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
987+ * GNU Lesser General Public License for more details.
988+ *
989+ * You should have received a copy of the GNU Lesser General Public License
990+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
991+ *
992+ * Authored by: Gary Wang <gary.wang@canonical.com>
993+ */
994+
995+#ifndef ONEDRIVE_API_SYNCMANAGER_H_
996+#define ONEDRIVE_API_SYNCMANAGER_H_
997+
998+#include <onedrive/api/taskqueue.h>
999+#include <onedrive/api/downloadtask.h>
1000+#include <onedrive/api/uploadtask.h>
1001+#include <onedrive/api/visibility.h>
1002+
1003+#include <memory>
1004+#include <vector>
1005+
1006+namespace onedrive {
1007+namespace api {
1008+
1009+class ClientPriv;
1010+class SyncManagerPriv;
1011+
1012+/*!
1013+ \class SyncManager
1014+ \brief SyncManager handles all the requests to upload and download.
1015+ It's constructed around two threads for content synchronization. One for content upload to cloud, another for cloud item download to local.
1016+ Both thread are running asynchronously.
1017+ Calls \sa add_download_task() by passing a content id list for cloud content download,
1018+ Calls \sa add_upload_tasks() by passing a local file path for local content upload.
1019+ */
1020+
1021+class ONEDRIVE_API_DLL_PUBLIC SyncManager {
1022+ public:
1023+ typedef std::shared_ptr<SyncManager> Ptr;
1024+
1025+ typedef TaskQueue<DownloadTask::Ptr> DownloadList;
1026+
1027+ typedef TaskQueue<UploadTask::Ptr> UploadList;
1028+
1029+ typedef std::vector<std::string> Stringlist;
1030+
1031+ virtual ~SyncManager() = default;
1032+
1033+ SyncManager(const SyncManager&) = delete;
1034+
1035+ SyncManager& operator=(const SyncManager &) = delete;
1036+
1037+ /*!
1038+ * \brief Starts to run download or upload tasks from sync-up thread.
1039+ * The tasks can be resumed by sync-up thread if sync manager is paused or canceled before.
1040+ * \sa pause(), cancel()
1041+ */
1042+ void start();
1043+
1044+ /*!
1045+ * \brief Cancels all download or upload tasks from sync-up thread if sync manager is running.
1046+ * \note A canceled download or upload task has no chance to run again by sync-up thread.
1047+ * \sa start(), pause()
1048+ */
1049+ void cancel();
1050+
1051+ /*!
1052+ * \brief Pauses download or upload task from sync-up thread if sync manager is running.
1053+ * Sync-up thread can continue to run previous paused task by calling \sa start()
1054+ * \sa start(), cancel()
1055+ */
1056+ void pause();
1057+
1058+ /*!
1059+ * \brief Pushes a content id \a contentid_list into download queue.
1060+ * \return download task item that is pushed in sync-up manager.
1061+ * \throw std::runtime_error if error occurs.
1062+ * \sa add_download_tasks(), DownloadTask
1063+ */
1064+ DownloadTask::Ptr add_download_task(const std::string &content_id);
1065+
1066+ /*!
1067+ * \brief Pushes a download buffer callback item \a buffer_cb_item into download queue.
1068+ * Each download buffer consists of the following fields
1069+ * - `write_cb` (std::function<size_t(void *dest, size_t buf_size)>)
1070+ * buffer reading callback function.
1071+ * The buffer area pointed at by the pointer \a dest should be filled up with at most \a buf_size number of bytes.
1072+ * - `content_id` (string)
1073+ * The id of content on onedrive.
1074+ * \return download task item that is pushed in sync-up manager.
1075+ * \throw std::runtime_error if error occurs.
1076+ * \sa add_download_tasks(), DownloadTask
1077+ */
1078+ DownloadTask::Ptr add_download_task(const DownloadBufferCb &buffer_cb_item);
1079+
1080+ /*!
1081+ * \brief Pushes a upload request item \a reqeust_item to sync manager and add regarding upload task into upload queue.
1082+ * A upload request consists of the following fields
1083+ * - `file_path` (string)
1084+ * local file path.
1085+ * - `folder_id` (string)
1086+ * onedrive folder id which stores content in uploads folder.
1087+ * - `content_name` (string)
1088+ * uploaded content name.
1089+ * If content_name is empty, local file name will be used as a content name displayed on onedrive.
1090+ * If folder_id is empty, content will be uploaded into root folder.
1091+ * \return upload task item that is pushed in sync-up manager.
1092+ * \throw std::runtime_error if error occurs.
1093+ * \note A file name can not contain any of following characters:
1094+ * '\', '/', ':', '*', '?', '"', '<', '>', '|'
1095+ * \note Sync manager will detect if the uploading file is already existing on cloud,
1096+ * if so, it simply sets the status of upload task completed to avoid duplicate upload.
1097+ * \sa add_download_tasks(), UploadRequest, UploadTask,
1098+ */
1099+ UploadTask::Ptr add_upload_task(const UploadRequest &reqeust_item);
1100+
1101+ /*!
1102+ * \brief Pushes a upload callback item \a buffer_cb to sync manager and add regarding upload task into upload queue.
1103+ * A upload buffer consists of the following fields
1104+ * - `read_cb` (std::function<size_t(void *dest, size_t buf_size)>)
1105+ * buffer reading callback function.
1106+ * The buffer area pointed at by the pointer \a dest should be filled up with at most \a buf_size number of bytes.
1107+ * - `buffer_size` (size_t)
1108+ * total size of data buffers.
1109+ * - `folder_id` (string)
1110+ * onedrive folder id which stores content in uploads folder.
1111+ * - `content_name` (string)
1112+ * uploaded content name, should not be empty.
1113+ * If folder_id is empty, content will be uploaded into root folder.
1114+ * \return upload task item that are pushed in sync-up manager.
1115+ * \throw std::runtime_error if error occurs.
1116+ * \note A file name can not contain any of following characters:
1117+ * '\', '/', ':', '*', '?', '"', '<', '>', '|'
1118+ * \sa add_download_tasks(), UploadRequest, UploadTask,
1119+ */
1120+ UploadTask::Ptr add_upload_task(const UploadBufferCb &buffer_cb);
1121+
1122+ /*!
1123+ * \brief Returns a download task list hold by sync up manager.
1124+ * Each item in the list contains basic information of associated task.
1125+ * \sa upload_queue(), DownloadTask
1126+ */
1127+ DownloadList download_queue();
1128+
1129+ /*!
1130+ * \brief Returns a upload task list hold by sync up manager.
1131+ * Each item in the list contains basic information of associated task.
1132+ * \sa download_queue(), UploadTask
1133+ */
1134+ UploadList upload_queue();
1135+
1136+private:
1137+ SyncManager(ClientPriv* client_priv);
1138+
1139+ friend class ClientPriv;
1140+
1141+ std::shared_ptr<SyncManagerPriv> p_;
1142+};
1143+
1144+}
1145+}
1146+
1147+#endif // ONEDRIVE_API_SYNCMANAGER_H_
1148
1149=== added file 'include/onedrive/api/task.h'
1150--- include/onedrive/api/task.h 1970-01-01 00:00:00 +0000
1151+++ include/onedrive/api/task.h 2016-09-30 08:26:58 +0000
1152@@ -0,0 +1,119 @@
1153+/*
1154+ * Copyright © 2016 Canonical Ltd.
1155+ *
1156+ * This program is free software: you can redistribute it and/or modify it
1157+ * under the terms of the GNU Lesser General Public License version 3,
1158+ * as published by the Free Software Foundation.
1159+ *
1160+ * This program is distributed in the hope that it will be useful,
1161+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1162+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1163+ * GNU Lesser General Public License for more details.
1164+ *
1165+ * You should have received a copy of the GNU Lesser General Public License
1166+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1167+ *
1168+ * Authored by: Gary Wang <gary.wang@canonical.com>
1169+ */
1170+
1171+#ifndef ONEDRIVE_API_TASK_H_
1172+#define ONEDRIVE_API_TASK_H_
1173+
1174+#include <onedrive/api/visibility.h>
1175+#include <functional>
1176+#include <string>
1177+
1178+namespace onedrive {
1179+namespace api {
1180+
1181+/*!
1182+ \class Task
1183+ \brief Task is an abstract class that defines common interfaces for upload and download task.
1184+ */
1185+
1186+class ONEDRIVE_API_DLL_PUBLIC Task {
1187+public:
1188+ /*!
1189+ * \brief The Status enum indicates current status of this task.
1190+ */
1191+ enum class Status {
1192+ Unstart, ///< Task is in queue and sync manager does not run this task yet.
1193+ Running, ///< Task is being processed by sync manager.
1194+ Canceled, ///< Task is in canceled status, it is caused by the call from Client::cancel_sync().
1195+ Paused, ///< Task is in paused status, it is caused by the call from Client::pause_sync().
1196+ Broken, ///< Task is broken when sync manager failed to download/upload a task after several times trying.
1197+ Complete, ///< Task is completed.
1198+ };
1199+
1200+ /*!
1201+ * \brief The name conflict enum which can be specified the behavior to use if the file already exists.
1202+ * The default for PUT is replace.
1203+ */
1204+ enum class NameConflictBehavior {
1205+ Fail, ///<Failed if the file already exists.
1206+ Replace, ///<Replace current content if the file already exists.
1207+ Rename ///<Automatically renamed by onedrive if the file already exists.
1208+ };
1209+
1210+ typedef std::function<void(float)> ProgressHandler;
1211+
1212+ typedef std::function<void(Status)> StatusHandler;
1213+
1214+ typedef std::function<size_t(void *dest, size_t buf_size)> Buffer_Callback;
1215+
1216+ virtual ~Task() = default;
1217+
1218+ /*!
1219+ * \brief Returns a display name of cloud content on onedrive.
1220+ */
1221+ virtual const std::string & content_name() const = 0;
1222+
1223+ /*!
1224+ * \brief Returns cloud content local storage file path.
1225+ */
1226+ virtual const std::string & file_path() const = 0;
1227+
1228+ /*!
1229+ * \brief Contains the error code if an error occurs during task running.
1230+ */
1231+ virtual const std::string & error_code() const = 0;
1232+
1233+ /*!
1234+ * \brief Contains the error string if an error occurs during task running.
1235+ */
1236+ virtual const std::string & error_message() const = 0;
1237+
1238+ /*!
1239+ * \brief Returns a item task url.
1240+ * \note the url will be expried after a period of time.
1241+ */
1242+ virtual const std::string & task_url() const = 0;
1243+
1244+ /*!
1245+ * \brief Returns current download or upload item sync-up status.
1246+ */
1247+ virtual Task::Status status() const = 0;
1248+
1249+ /*!
1250+ * \brief Handler for download or upload progress of a task.
1251+ * \sa Task::ProgressHandler
1252+ */
1253+ virtual Task::ProgressHandler & progress_changed() = 0;
1254+
1255+ /*!
1256+ * \brief Handler for download or upload progress of a task.
1257+ * \sa Task::StatusHandler
1258+ */
1259+ virtual Task::StatusHandler & status_changed() = 0;
1260+
1261+ /*!
1262+ * \brief Cancel the task.
1263+ * \sa Task::StatusHandler
1264+ */
1265+ virtual void cancel() = 0;
1266+};
1267+
1268+}
1269+}
1270+
1271+#endif // ONEDRIVE_API_TASK_H_
1272
1273=== added file 'include/onedrive/api/taskqueue.h'
1274--- include/onedrive/api/taskqueue.h 1970-01-01 00:00:00 +0000
1275+++ include/onedrive/api/taskqueue.h 2016-09-30 08:26:58 +0000
1276@@ -0,0 +1,131 @@
1277+/*
1278+ * Copyright © 2016 Canonical Ltd.
1279+ *
1280+ * This program is free software: you can redistribute it and/or modify it
1281+ * under the terms of the GNU Lesser General Public License version 3,
1282+ * as published by the Free Software Foundation.
1283+ *
1284+ * This program is distributed in the hope that it will be useful,
1285+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1286+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1287+ * GNU Lesser General Public License for more details.
1288+ *
1289+ * You should have received a copy of the GNU Lesser General Public License
1290+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1291+ *
1292+ * Authored by: Gary Wang <gary.wang@canonical.com>
1293+ */
1294+
1295+#ifndef ONEDRIVE_API_TASKQUEUE_H_
1296+#define ONEDRIVE_API_TASKQUEUE_H_
1297+
1298+#include <memory>
1299+#include <deque>
1300+#include <mutex>
1301+
1302+namespace onedrive {
1303+namespace api {
1304+
1305+/*!
1306+ \class TaskQueue
1307+ \brief A thread-safe deque template.
1308+ */
1309+template<typename T, typename Container = std::deque<T>>
1310+class TaskQueue {
1311+ public:
1312+ typedef std::shared_ptr<TaskQueue> Ptr;
1313+ typedef typename Container::size_type size_type;
1314+ typedef typename Container::const_iterator const_iterator;
1315+
1316+ TaskQueue() = default;
1317+
1318+ virtual ~TaskQueue() = default;
1319+
1320+ TaskQueue(TaskQueue &&queue) {
1321+ std::lock_guard<std::mutex> lock(mutex_);
1322+ tasks_ = std::move(queue.tasks_);
1323+ }
1324+
1325+ TaskQueue(const TaskQueue &queue) {
1326+ std::lock_guard<std::mutex> lock(mutex_);
1327+ tasks_ = queue.tasks_;
1328+ }
1329+
1330+ TaskQueue &operator= (const TaskQueue &queue) {
1331+ if (this != &queue) {
1332+ std::lock_guard<std::mutex> lock1(mutex_);
1333+ std::lock_guard<std::mutex> lock2(queue.mutex_);
1334+ tasks_ = queue.tasks_;
1335+ }
1336+
1337+ return *this;
1338+ }
1339+
1340+ typename Container::iterator begin() {
1341+ std::lock_guard<std::mutex> lock(mutex_);
1342+ return tasks_.begin();
1343+ }
1344+
1345+ typename Container::iterator end() {
1346+ std::lock_guard<std::mutex> lock(mutex_);
1347+ return tasks_.end();
1348+ }
1349+
1350+ typename Container::iterator cbegin() const {
1351+ std::lock_guard<std::mutex> lock(mutex_);
1352+ return tasks_.cbegin();
1353+ }
1354+
1355+ typename Container::iterator cend() const {
1356+ std::lock_guard<std::mutex> lock(mutex_);
1357+ return tasks_.cend();
1358+ }
1359+
1360+ size_type size() const {
1361+ std::lock_guard<std::mutex> lock(mutex_);
1362+ return tasks_.size();
1363+ }
1364+
1365+ bool empty() const {
1366+ std::lock_guard<std::mutex> lock(mutex_);
1367+ return tasks_.empty();
1368+ }
1369+
1370+ void push(const T &task) {
1371+ std::lock_guard<std::mutex> lock(mutex_);
1372+ tasks_.push_back(task);
1373+ }
1374+
1375+ void push(const TaskQueue & queue) {
1376+ std::lock_guard<std::mutex> lock(mutex_);
1377+ for (const T & task: queue.tasks_){
1378+ tasks_.push_back(task);
1379+ }
1380+ }
1381+
1382+ bool try_pop(T &task) {
1383+ std::lock_guard<std::mutex> lock(mutex_);
1384+
1385+ if (tasks_.empty())
1386+ return false;
1387+
1388+ task = tasks_.front();
1389+ tasks_.pop_front();
1390+ return true;
1391+ }
1392+
1393+ const T & operator[](int index) const {
1394+ std::lock_guard<std::mutex> lock(mutex_);
1395+ return tasks_[index];
1396+ }
1397+
1398+ private:
1399+ Container tasks_;
1400+
1401+ mutable std::mutex mutex_;
1402+};
1403+
1404+}
1405+}
1406+
1407+#endif // ONEDRIVE_API_TASKQUEUE_H_
1408
1409=== added file 'include/onedrive/api/uploadtask.h'
1410--- include/onedrive/api/uploadtask.h 1970-01-01 00:00:00 +0000
1411+++ include/onedrive/api/uploadtask.h 2016-09-30 08:26:58 +0000
1412@@ -0,0 +1,176 @@
1413+/*
1414+ * Copyright © 2016 Canonical Ltd.
1415+ *
1416+ * This program is free software: you can redistribute it and/or modify it
1417+ * under the terms of the GNU Lesser General Public License version 3,
1418+ * as published by the Free Software Foundation.
1419+ *
1420+ * This program is distributed in the hope that it will be useful,
1421+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1422+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1423+ * GNU Lesser General Public License for more details.
1424+ *
1425+ * You should have received a copy of the GNU Lesser General Public License
1426+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1427+ *
1428+ * Authored by: Gary Wang <gary.wang@canonical.com>
1429+ */
1430+
1431+#ifndef ONEDRIVE_API_UPLOADTASK_H_
1432+#define ONEDRIVE_API_UPLOADTASK_H_
1433+
1434+#include <onedrive/api/task.h>
1435+#include <onedrive/api/visibility.h>
1436+
1437+#include <memory>
1438+#include <vector>
1439+
1440+namespace Json {
1441+ class Value;
1442+}
1443+
1444+namespace onedrive {
1445+namespace api {
1446+
1447+class TaskHandler;
1448+
1449+/*!
1450+ \struct UploadRequest
1451+ \brief UploadRequest is a upload request item which consists of a upload folder id, up-front buffer size,
1452+ upload content name
1453+ */
1454+struct ONEDRIVE_API_DLL_PUBLIC UploadRequest
1455+{
1456+ UploadRequest(std::string local_file_path,
1457+ std::string parent_folder_id,
1458+ std::string upload_file_name,
1459+ Task::NameConflictBehavior conflict_name_behavior = Task::NameConflictBehavior::Replace)
1460+ :file_path(local_file_path),
1461+ folder_id(parent_folder_id),
1462+ content_name(upload_file_name),
1463+ conflict_behavior(conflict_name_behavior){
1464+ }
1465+
1466+ std::string file_path;
1467+ std::string folder_id;
1468+ std::string content_name;
1469+ Task::NameConflictBehavior conflict_behavior;
1470+};
1471+typedef std::vector<UploadRequest> UploadRequestList;
1472+
1473+/*!
1474+ \struct UploadBufferCb
1475+ \brief UploadBufferCb is a upload request item which consists of a upload folder id, upload buffer size,
1476+ upload content name and reading callback function allows content data can be received in buffering via call
1477+ back function.
1478+*/
1479+struct ONEDRIVE_API_DLL_PUBLIC UploadBufferCb
1480+{
1481+ UploadBufferCb(Task::Buffer_Callback read_callback,
1482+ size_t upload_buf_size,
1483+ std::string parent_folder_id,
1484+ std::string upload_file_name,
1485+ Task::NameConflictBehavior conflict_name_behavior = Task::NameConflictBehavior::Replace)
1486+ :read_cb(read_callback),
1487+ buffer_size(upload_buf_size),
1488+ folder_id(parent_folder_id),
1489+ content_name(upload_file_name),
1490+ conflict_behavior(conflict_name_behavior){
1491+ }
1492+
1493+ Task::Buffer_Callback read_cb;
1494+ size_t buffer_size;
1495+ std::string folder_id;
1496+ std::string content_name;
1497+ Task::NameConflictBehavior conflict_behavior = Task::NameConflictBehavior::Replace;
1498+};
1499+typedef std::vector<UploadBufferCb> UploadBufferCbList;
1500+
1501+class UploadTaskPriv;
1502+class CloudItem;
1503+
1504+/*!
1505+ \class UploadTask
1506+ \brief UploadTask is a task item that can be accessed from application layer to fetch
1507+ basic upload item information, also it's used for content upload by sync manager.
1508+ */
1509+class ONEDRIVE_API_DLL_PUBLIC UploadTask : public Task {
1510+public:
1511+ typedef std::shared_ptr<UploadTask> Ptr;
1512+
1513+ virtual ~UploadTask() = default;
1514+
1515+ UploadTask& operator=(const UploadTask& ) = delete;
1516+
1517+ /*!
1518+ * \brief Returns a display name of local content.
1519+ */
1520+ const std::string & content_name() const override;
1521+
1522+ /*!
1523+ * \brief Returns uploaded local content file path.
1524+ */
1525+ const std::string & file_path() const override;
1526+
1527+ /*!
1528+ * \brief Returns download url assigned by onedrive for this task.
1529+ * \note this url will be expried after a period of time.
1530+ */
1531+ const std::string & task_url() const override;
1532+
1533+ /*!
1534+ * \brief Contains the error code if an error occurs during content uploading.
1535+ */
1536+ const std::string & error_code() const override;
1537+
1538+ /*!
1539+ * \brief Contains the error string if an error occurs during content uploading.
1540+ */
1541+ const std::string & error_message() const override;
1542+
1543+ /*!
1544+ * \brief Returns current sync-up status for this task.
1545+ */
1546+ Task::Status status() const override;
1547+
1548+ /*!
1549+ * \brief Handler for upload progress of a task.
1550+ * \sa Task::ProgressHandler
1551+ */
1552+ Task::ProgressHandler & progress_changed() override;
1553+
1554+ /*!
1555+ * \brief Handler for upload status of a task.
1556+ * \sa Task::StatusHandler
1557+ */
1558+ Task::StatusHandler & status_changed() override;
1559+
1560+ /*!
1561+ * \brief Returns a cloud item object associated with the uploaded content.
1562+ * \note Returns nullptr if task failed to upload regarding content on onedrive.
1563+ */
1564+ std::shared_ptr<CloudItem> upload_item() const;
1565+
1566+ /*!
1567+ * \brief cancel the task.
1568+ * \sa Task::StatusHandler
1569+ */
1570+ void cancel() override;
1571+
1572+ /*!
1573+ * \brief Returns file size of upload content.
1574+ */
1575+ size_t file_size() const;
1576+
1577+private:
1578+ UploadTask(std::shared_ptr<UploadTaskPriv> p);
1579+
1580+ friend class SyncManagerPriv;
1581+
1582+ std::shared_ptr<UploadTaskPriv> p_;
1583+};
1584+
1585+}
1586+}
1587+
1588+#endif // ONEDRIVE_API_UPLOADTASK_H_
1589
1590=== added file 'include/onedrive/api/visibility.h'
1591--- include/onedrive/api/visibility.h 1970-01-01 00:00:00 +0000
1592+++ include/onedrive/api/visibility.h 2016-09-30 08:26:58 +0000
1593@@ -0,0 +1,30 @@
1594+/*
1595+ * Copyright (C) 2016 Canonical, Ltd.
1596+ *
1597+ * This library is free software; you can redistribute it and/or modify it under
1598+ * the terms of version 3 of the GNU Lesser General Public License as published
1599+ * by the Free Software Foundation.
1600+ *
1601+ * This library is distributed in the hope that it will be useful, but WITHOUT
1602+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1603+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
1604+ * details.
1605+ *
1606+ * You should have received a copy of the GNU Lesser General Public License
1607+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1608+ *
1609+ * Author: Gary Wang <gary.wang@canonical.com>
1610+ */
1611+
1612+#ifndef ONEDRIVE_API_VISIBILITY_H_
1613+#define ONEDRIVE_API_VISIBILITY_H_
1614+
1615+#if __GNUC__ >= 4
1616+#define ONEDRIVE_API_DLL_PUBLIC __attribute__ ((visibility ("default")))
1617+#define ONEDRIVE_API_DLL_LOCAL __attribute__ ((visibility ("hidden")))
1618+#else
1619+#define ONEDRIVE_API_DLL_PUBLIC
1620+#define ONEDRIVE_API_DLL_LOCAL
1621+#endif
1622+
1623+#endif // ONEDRIVE_API_VISIBILITY_H_
1624
1625=== modified file 'provider/CMakeLists.txt'
1626--- provider/CMakeLists.txt 2016-09-26 04:27:03 +0000
1627+++ provider/CMakeLists.txt 2016-09-30 08:26:58 +0000
1628@@ -0,0 +1,32 @@
1629+find_package(PkgConfig REQUIRED)
1630+find_package(Boost COMPONENTS filesystem system thread REQUIRED)
1631+
1632+pkg_check_modules(STORAGE_FRAMEWORK_PROVIDER storage-framework-provider-1 REQUIRED)
1633+
1634+include_directories(${CMAKE_CURRENT_BINARY_DIR} ${STORAGE_FRAMEWORK_PROVIDER_INCLUDE_DIRS})
1635+
1636+add_definitions(-DBOOST_THREAD_VERSION=4)
1637+
1638+add_executable(onedrive-provider-bin OnedriveProvider.cpp)
1639+
1640+target_link_libraries(
1641+ onedrive-provider-bin
1642+ onedrive-provider
1643+
1644+ ${Boost_LIBRARIES}
1645+ ${STORAGE_FRAMEWORK_PROVIDER_LDFLAGS}
1646+)
1647+
1648+SET_TARGET_PROPERTIES(onedrive-provider-bin
1649+ PROPERTIES OUTPUT_NAME onedrive-provider
1650+)
1651+
1652+install(
1653+ TARGETS onedrive-provider-bin
1654+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
1655+)
1656+
1657+install(
1658+ FILES ${CMAKE_CURRENT_SOURCE_DIR}/com.canonical.StorageFramework.Provider.OnedriveProvider.service
1659+ DESTINATION /usr/share/dbus-1/services
1660+)
1661
1662=== added file 'provider/OnedriveProvider.cpp'
1663--- provider/OnedriveProvider.cpp 1970-01-01 00:00:00 +0000
1664+++ provider/OnedriveProvider.cpp 2016-09-30 08:26:58 +0000
1665@@ -0,0 +1,634 @@
1666+/*
1667+ * Copyright (C) 2016 Canonical Ltd
1668+ *
1669+ * This program is free software: you can redistribute it and/or modify
1670+ * it under the terms of the GNU Lesser General Public License version 3 as
1671+ * published by the Free Software Foundation.
1672+ *
1673+ * This program is distributed in the hope that it will be useful,
1674+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1675+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1676+ * GNU Lesser General Public License for more details.
1677+ *
1678+ * You should have received a copy of the GNU Lesser General Public License
1679+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1680+ *
1681+ * Authors: Gary Wang <gary.wang@canonical.com>
1682+ */
1683+
1684+#include "OnedriveProvider.h"
1685+#include <unity/storage/provider/ProviderBase.h>
1686+#include <unity/storage/provider/Server.h>
1687+#include <unity/storage/provider/TempfileUploadJob.h>
1688+#include <unity/storage/provider/UploadJob.h>
1689+#include <unity/storage/provider/DownloadJob.h>
1690+#include <unity/storage/provider/metadata_keys.h>
1691+#include <unity/storage/provider/Exceptions.h>
1692+
1693+#include <boost/thread.hpp>
1694+#include <boost/thread/future.hpp>
1695+#include <boost/filesystem.hpp>
1696+#include <boost/make_shared.hpp>
1697+
1698+#include <unistd.h>
1699+#include <sys/socket.h>
1700+#include <inttypes.h>
1701+#include <unistd.h>
1702+#include <iostream>
1703+#include <memory>
1704+#include <mutex>
1705+#include <stdexcept>
1706+#include <condition_variable>
1707+
1708+#include <onedrive/api/client.h>
1709+#include <onedrive/api/uploadtask.h>
1710+#include <onedrive/api/syncmanager.h>
1711+#include <onedrive/api/cloudresource.h>
1712+#include <onedrive/api/cloudcontent.h>
1713+#include <onedrive/api/cloudfolder.h>
1714+#include <onedrive/api/exceptions.h>
1715+
1716+using namespace std;
1717+using namespace unity::storage;
1718+using namespace unity::storage::provider;
1719+using namespace onedrive::api;
1720+
1721+using boost::make_ready_future;
1722+using boost::make_exceptional_future;
1723+
1724+namespace {
1725+ static const int TIME_OUT = 10;
1726+
1727+ static const char *FOLDER_TYPE[] = {"normal", "pictures", "music", "videos", "message", "docs", "app", "sync"};
1728+ static const char *CONTENT_TYPE[] = {"all", "image", "audio", "video", "other", "doc", "spreadsheet", "ppt"};
1729+ static const char *STATUS[] = {"unstart", "running", "canceled", "paused", "broken", "complete"};
1730+ static char constexpr SIZE_IN_BYTES[] = "size_in_bytes";
1731+
1732+ string make_job_id()
1733+ {
1734+ static int last_upload_id = 0;
1735+ return to_string(++last_upload_id);
1736+ }
1737+
1738+ string status_to_string(Task::Status status)
1739+ {
1740+ return STATUS[int(status)];
1741+ }
1742+
1743+ string folder_type_to_string(CloudFolder::Type type)
1744+ {
1745+ return FOLDER_TYPE[int(type)];
1746+ }
1747+
1748+ string content_type_to_string(CloudContent::Type type)
1749+ {
1750+ return CONTENT_TYPE[int(type)];
1751+ }
1752+
1753+ string time_to_iso(time_t t)
1754+ {
1755+ char buf[sizeof "2016-08-11T15:10:07"];
1756+ strftime(buf, sizeof buf, "%FT%T", gmtime(&t));
1757+ return buf;
1758+ }
1759+
1760+ Item content_to_item(CloudResource::Ptr resource)
1761+ {
1762+ Item item;
1763+ item.item_id = resource->id();
1764+ item.parent_ids = {resource->folder_id()};
1765+ item.name = resource->name();
1766+ item.etag = resource->etag();
1767+ item.metadata["owner"] = resource->owner();
1768+ item.metadata[provider::CREATION_TIME] = time_to_iso(resource->created_date());
1769+ item.metadata[provider::LAST_MODIFIED_TIME] = time_to_iso(resource->updated_date());
1770+ if (resource->property() == CloudResource::Property::Folder) {
1771+ item.type = ItemType::folder;
1772+ auto folder = std::static_pointer_cast<onedrive::api::CloudFolder>(resource);
1773+ item.metadata["folder_type"] = folder_type_to_string(folder->folder_type());
1774+ item.metadata["folder_path"] = folder->folder_path();
1775+ } else if (resource->property() == CloudResource::Property::Content){
1776+ item.type = ItemType::file;
1777+ auto file = std::static_pointer_cast<onedrive::api::CloudContent>(resource);
1778+ item.metadata["suffix"] = file->suffix();
1779+ item.metadata["content_type"] = content_type_to_string(file->type());
1780+
1781+ item.metadata[provider::SIZE_IN_BYTES] = file->content_size();
1782+ item.metadata["description"] = file->description();
1783+ item.metadata["thumbnail_url"] = file->thumbnail_url();
1784+ item.metadata["big_thumbnail_url"] = file->big_thumbnail_url();
1785+ item.metadata["present_url"] = file->big_thumbnail_url();
1786+ }
1787+
1788+ return item;
1789+ }
1790+}
1791+
1792+class OnedriveUploadJob : public UploadJob
1793+{
1794+public:
1795+ OnedriveUploadJob(string const& upload_id,
1796+ Client::Ptr client,
1797+ string const& parent_id,
1798+ string const& file_name,
1799+ int64_t size,
1800+ bool allow_overwrite);
1801+
1802+ boost::future<void> cancel() override;
1803+ boost::future<Item> finish() override;
1804+private:
1805+ boost::future<tuple<bool, string>> upload_data();
1806+ void stop_and_cancel();
1807+private:
1808+ ssize_t feed_size;
1809+ string parent_id_;
1810+ string file_name_;
1811+ int64_t upload_size_;
1812+ bool allow_overwrite_;
1813+
1814+ boost::future<tuple<bool, string>> upload_future_;
1815+
1816+ std::mutex mutex_;
1817+
1818+ UploadTask::Ptr task_;
1819+ Client::Ptr client_;
1820+};
1821+
1822+class OnedriveDownloadJob : public DownloadJob
1823+{
1824+public:
1825+ using DownloadJob::DownloadJob;
1826+
1827+ OnedriveDownloadJob(string const& download_id,
1828+ string const& item_id,
1829+ Client::Ptr client);
1830+
1831+ boost::future<void> cancel() override;
1832+ boost::future<void> finish() override;
1833+private:
1834+ boost::future<tuple<bool, string>> download_data();
1835+ void send_data();
1836+ void stop_and_cancel();
1837+private:
1838+ string item_id_;
1839+ boost::future<tuple<bool, string>> download_future_;
1840+
1841+ std::mutex mutex_;
1842+
1843+ DownloadTask::Ptr task_;
1844+ Client::Ptr client_;
1845+};
1846+
1847+OnedriveProvider::OnedriveProvider()
1848+ : client_(std::make_shared<Client>(TIME_OUT))
1849+{
1850+}
1851+
1852+boost::future<ItemList> OnedriveProvider::roots(Context const& ctx)
1853+{
1854+ set_access_token(ctx);
1855+
1856+ return boost::async([this](){
1857+ try {
1858+ auto root_folder_id = client_->cloud_root_folder_id();
1859+
1860+ ItemList roots = {
1861+ {root_folder_id, {}, "root", "", ItemType::root, {}}
1862+ };
1863+
1864+ return make_ready_future<ItemList>(roots);
1865+ } catch (runtime_error &e) {
1866+ return make_exceptional_future<ItemList>(
1867+ RemoteCommsException(string("OnedriveProvider::roots(): failed: ") + e.what()));
1868+ }
1869+ });
1870+}
1871+
1872+boost::future<tuple<ItemList,string>> OnedriveProvider::list(
1873+ string const& item_id, string const& page_token,
1874+ Context const& ctx)
1875+{
1876+ set_access_token(ctx);
1877+
1878+ int page_token_index = 0;
1879+ if (!page_token.empty()) {
1880+ try {
1881+ page_token_index = stoi(page_token);
1882+ } catch (invalid_argument &e) {
1883+ return make_exceptional_future<tuple<ItemList,string>>(
1884+ InvalidArgumentException(string("OnedriveProvider::list(): invalid page token: ") + e.what()));
1885+ }
1886+ }
1887+
1888+ return boost::async([this, item_id, page_token_index](){
1889+ try {
1890+ const int count_per_page = 50;
1891+ int start_index = 1 + page_token_index * count_per_page;
1892+ auto content_list = client_->cloud_content_list(start_index, count_per_page,
1893+ CloudContent::Type::All, item_id);
1894+
1895+ ItemList roots;
1896+ for (const auto & content: content_list) {
1897+ roots.push_back(content_to_item(content));
1898+ }
1899+
1900+ int offset = 0;
1901+ boost::promise<tuple<ItemList,string>> prom;
1902+ if (content_list.size() >= count_per_page) {
1903+ offset++;
1904+ }
1905+ prom.set_value(make_tuple(roots, std::to_string(page_token_index + offset)));
1906+
1907+ return prom.get_future();
1908+ } catch (InvalidIDException &e) {
1909+ return make_exceptional_future<tuple<ItemList,string>>(
1910+ NotExistsException(string("OnedriveProvider::list(): failed: ") + e.what(), item_id));
1911+ } catch (runtime_error &e) {
1912+ return make_exceptional_future<tuple<ItemList,string>>(
1913+ RemoteCommsException(string("OnedriveProvider::list(): failed: ") + e.what()));
1914+ }
1915+ });
1916+}
1917+
1918+boost::future<ItemList> OnedriveProvider::lookup(
1919+ string const& parent_id, string const& name,
1920+ Context const& ctx)
1921+{
1922+ set_access_token(ctx);
1923+
1924+ return boost::async([this, parent_id, name](){
1925+ try {
1926+ const int count_per_page = 50;
1927+ int page_token_index = 0;
1928+ int start_index = 0;
1929+
1930+ ItemList roots;
1931+ do {
1932+ page_token_index++;
1933+ start_index = 1 + (page_token_index - 1) * count_per_page;
1934+ auto content_list = client_->cloud_content_list(start_index, count_per_page,
1935+ CloudContent::Type::All, parent_id);
1936+
1937+ for (const auto & content: content_list) {
1938+ if (content->name().find(name) != string::npos) {
1939+ roots.push_back(content_to_item(content));
1940+ }
1941+ }
1942+
1943+ if (content_list.size() < count_per_page)
1944+ break;
1945+ } while (true);
1946+
1947+ return make_ready_future<ItemList>(roots);
1948+ } catch (InvalidIDException &e) {
1949+ return make_exceptional_future<ItemList>(
1950+ NotExistsException(string("OnedriveProvider::lookup(): folder not exists: ") + e.what(), parent_id));
1951+ } catch (runtime_error &e) {
1952+ return make_exceptional_future<ItemList>(
1953+ RemoteCommsException(string("OnedriveProvider::lookup(): failed: ") + e.what()));
1954+ }
1955+ });
1956+}
1957+
1958+boost::future<Item> OnedriveProvider::metadata(string const& item_id,
1959+ Context const& ctx)
1960+{
1961+ set_access_token(ctx);
1962+
1963+ return boost::async([this, item_id](){
1964+ try {
1965+ auto content = client_->metadata(item_id);
1966+ return make_ready_future<Item>(content_to_item(content));
1967+ } catch (NonExistentException &e) {
1968+ return make_exceptional_future<Item>(
1969+ NotExistsException(string("OnedriveProvider::metadata(): content not exists: ") + e.what(), item_id));
1970+ } catch (runtime_error &e) {
1971+ return make_exceptional_future<Item>(
1972+ RemoteCommsException(string("OnedriveProvider::metadata(): failed: ") + e.what()));
1973+ }
1974+ });
1975+}
1976+
1977+boost::future<Item> OnedriveProvider::create_folder(
1978+ string const& parent_id, string const& name,
1979+ Context const& ctx)
1980+{
1981+ set_access_token(ctx);
1982+
1983+ return boost::async([this, parent_id, name](){
1984+ try {
1985+ auto content = client_->create_folder(name, parent_id);
1986+ return make_ready_future<Item>(content_to_item(content));
1987+ } catch (NonExistentException &e) {
1988+ return make_exceptional_future<Item>(
1989+ NotExistsException(string("OnedriveProvider::create_folder(): name: ") + e.what(), name));
1990+ } catch (runtime_error &e) {
1991+ return make_exceptional_future<Item>(
1992+ RemoteCommsException(string("OnedriveProvider::create_folder(): failed: ") + e.what()));
1993+ }
1994+ });
1995+}
1996+
1997+boost::future<unique_ptr<UploadJob>> OnedriveProvider::create_file(
1998+ string const& parent_id, string const& name,
1999+ int64_t size, string const& /*content_type*/, bool allow_overwrite,
2000+ Context const& ctx)
2001+{
2002+ set_access_token(ctx);
2003+
2004+ return make_ready_future(unique_ptr<UploadJob>(new OnedriveUploadJob(make_job_id(), client_, parent_id, name, size, allow_overwrite)));
2005+}
2006+
2007+boost::future<unique_ptr<UploadJob>> OnedriveProvider::update(
2008+ string const& item_id, int64_t size, string const& /*old_etag*/,
2009+ Context const& ctx)
2010+{
2011+ set_access_token(ctx);
2012+
2013+ return boost::async([this, item_id, size, ctx](){
2014+ try {
2015+ auto content = client_->metadata(item_id);
2016+ auto file_name = content->name();
2017+ auto parent_id = content->folder_id();
2018+
2019+ delete_item(item_id, ctx);
2020+
2021+ return create_file(parent_id, file_name, size, "", true, ctx);
2022+ } catch (runtime_error &e) {
2023+ return make_exceptional_future<unique_ptr<UploadJob>>(
2024+ RemoteCommsException(string("OnedriveProvider::update(): failed: ") + e.what()));
2025+ }
2026+ });
2027+}
2028+
2029+boost::future<unique_ptr<DownloadJob>> OnedriveProvider::download(
2030+ string const& item_id, Context const& ctx)
2031+{
2032+ set_access_token(ctx);
2033+
2034+ return make_ready_future(unique_ptr<DownloadJob>(new OnedriveDownloadJob(make_job_id(), item_id, client_)));
2035+}
2036+
2037+boost::future<void> OnedriveProvider::delete_item(
2038+ string const& item_id, Context const& ctx)
2039+{
2040+ set_access_token(ctx);
2041+
2042+ return boost::async([this, item_id](){
2043+ try {
2044+ Client::Stringlist content_id_list{{item_id}};
2045+ client_->delete_contents(content_id_list);
2046+ return make_ready_future();
2047+ } catch (ParameterInvalidException &e) {
2048+ return make_exceptional_future<void>(
2049+ NotExistsException(string("OnedriveProvider::delete_item(): failed: ") + e.what(), item_id));
2050+ } catch (runtime_error &e) {
2051+ return make_exceptional_future<void>(
2052+ RemoteCommsException(string("OnedriveProvider::delete_item(): failed: ") + e.what()));
2053+ }
2054+ });
2055+}
2056+
2057+boost::future<Item> OnedriveProvider::move(
2058+ string const& item_id, string const& new_parent_id,
2059+ string const& /*new_name*/, Context const& ctx)
2060+{
2061+ set_access_token(ctx);
2062+
2063+ return boost::async([this, item_id, new_parent_id](){
2064+ try {
2065+ Client::Stringlist folderlist;
2066+ Client::Stringlist contentlist{{item_id}};
2067+ client_->move_items(folderlist, contentlist, new_parent_id);
2068+ auto content = client_->metadata(item_id);
2069+ return make_ready_future<Item>(content_to_item(content));
2070+ } catch (NonExistentException &e) {
2071+ return make_exceptional_future<Item>(
2072+ NotExistsException(string("OnedriveProvider::move(): content or folder not exist: ") + e.what(), ""));
2073+ } catch (runtime_error &e) {
2074+ return make_exceptional_future<Item>(
2075+ RemoteCommsException(string("OnedriveProvider::move(): failed: ") + e.what()));
2076+ }
2077+ });
2078+}
2079+
2080+boost::future<Item> OnedriveProvider::copy(
2081+ string const& item_id, string const& new_parent_id,
2082+ string const& /*new_name*/, Context const& ctx)
2083+{
2084+ set_access_token(ctx);
2085+
2086+ return boost::async([this, item_id, new_parent_id](){
2087+ try {
2088+ Client::Stringlist content_list{{item_id}};
2089+ auto content_id = client_->copy_contents(content_list, new_parent_id)[0];
2090+ auto content = client_->metadata(content_id);
2091+ return make_ready_future<Item>(content_to_item(content));
2092+ } catch (NonExistentException &e) {
2093+ return make_exceptional_future<Item>(
2094+ NotExistsException(string("OnedriveProvider::copy(): content or folder not exist: ") + e.what(), item_id));
2095+ } catch (runtime_error &e) {
2096+ return make_exceptional_future<Item>(
2097+ RemoteCommsException(string("OnedriveProvider::copy(): failed: ") + e.what()));
2098+ }
2099+ });
2100+}
2101+
2102+void OnedriveProvider::set_access_token(Context const& ctx) {
2103+ auto access_token = boost::get<OAuth2Credentials>(ctx.credentials).access_token;
2104+ std::cout <<"onedrive access_token: " << access_token << std::endl;
2105+ client_->set_access_token(access_token);
2106+}
2107+
2108+OnedriveUploadJob::OnedriveUploadJob(string const &upload_id,
2109+ Client::Ptr client,
2110+ string const& parent_id,
2111+ string const& file_name,
2112+ int64_t size,
2113+ bool allow_overwrite)
2114+ : UploadJob(upload_id)
2115+ , parent_id_(parent_id)
2116+ , file_name_(file_name)
2117+ , upload_size_(size)
2118+ , allow_overwrite_(allow_overwrite)
2119+ , task_(nullptr)
2120+ , client_(client)
2121+{
2122+ upload_future_ = upload_data();
2123+}
2124+
2125+boost::future<void> OnedriveUploadJob::cancel()
2126+{
2127+ printf("cancel_upload('%s')\n", upload_id().c_str());
2128+ stop_and_cancel();
2129+
2130+ return make_ready_future();
2131+}
2132+
2133+boost::future<Item> OnedriveUploadJob::finish()
2134+{
2135+ printf("finish_upload('%s')\n", upload_id().c_str());
2136+ return boost::async([this](){
2137+ try {
2138+ auto upload_ctx = upload_future_.get();
2139+ auto upload_ok = get<0>(upload_ctx);
2140+ auto error_str = get<1>(upload_ctx);
2141+ if (upload_ok){
2142+ auto content = client_->metadata(task_->content_id());
2143+ return make_ready_future<Item>(content_to_item(content));
2144+ }
2145+
2146+ return make_exceptional_future<Item>(
2147+ RemoteCommsException(string("OnedriveUploadJob::finish(): failed: ") + error_str));
2148+ } catch (runtime_error &e) {
2149+ return make_exceptional_future<Item>(
2150+ RemoteCommsException(string("OnedriveUploadJob::finish(): failed: ") + e.what()));
2151+ }
2152+ });
2153+}
2154+
2155+boost::future<tuple<bool, string>> OnedriveUploadJob::upload_data()
2156+{
2157+ auto prom = boost::make_shared<boost::promise<tuple<bool, string>>>();
2158+
2159+ return boost::async([this, prom](){
2160+ std::lock_guard<std::mutex> guard(mutex_);
2161+
2162+ int socket_fd = read_socket();
2163+ UploadBufferList buffer_item_list{{[socket_fd](void *dest, size_t buf_size) -> size_t {
2164+ //data reading callback.
2165+ size_t read_size = read(socket_fd, dest, buf_size);
2166+ if (read_size == 0)
2167+ return -1;
2168+ return read_size;
2169+ }, (size_t)upload_size_, parent_id_, file_name_}};
2170+
2171+ try {
2172+ task_ = client_->syncmanager()->add_upload_tasks(buffer_item_list)[0];
2173+ task_->status_changed() = [this, prom](Task::Status status) {
2174+ std::cout << " status: " << status_to_string(status) << std::endl;
2175+ if (status == Task::Status::Complete){
2176+ prom->set_value(make_tuple(true, string()));
2177+ } else if (status == Task::Status::Canceled ||
2178+ status == Task::Status::Broken) {
2179+ prom->set_value(make_tuple(false, task_->error_string()));
2180+ }
2181+ };
2182+ task_->progress_changed() = [this](float percent) {
2183+ cout<< "uploading: " << task_->content_name() << " " << percent << endl;
2184+ };
2185+ } catch (runtime_error & e) {
2186+ prom->set_value(make_tuple(false, e.what()));
2187+ }
2188+
2189+ return prom->get_future();
2190+ });
2191+}
2192+
2193+void OnedriveUploadJob::stop_and_cancel()
2194+{
2195+ std::lock_guard<std::mutex> guard(mutex_);
2196+
2197+ if (task_ != nullptr &&
2198+ (task_->status() != Task::Status::Broken &&
2199+ task_->status() != Task::Status::Complete)) {
2200+ task_->cancel();
2201+ }
2202+}
2203+
2204+OnedriveDownloadJob::OnedriveDownloadJob(string const &download_id,
2205+ string const &item_id,
2206+ Client::Ptr client)
2207+ : DownloadJob(download_id)
2208+ , item_id_(item_id)
2209+ , task_(nullptr)
2210+ , client_(client)
2211+{
2212+ download_future_ = download_data();
2213+}
2214+
2215+boost::future<void> OnedriveDownloadJob::cancel()
2216+{
2217+ stop_and_cancel();
2218+
2219+ printf("cancel_download('%s')\n", download_id().c_str());
2220+ return make_ready_future();
2221+}
2222+
2223+boost::future<void> OnedriveDownloadJob::finish()
2224+{
2225+ return boost::async([this]() {
2226+ auto download_ctx = download_future_.get();
2227+ auto download_ok = get<0>(download_ctx);
2228+ auto error_str = get<1>(download_ctx);
2229+ if (download_ok){
2230+ return make_ready_future();
2231+ }
2232+
2233+ return make_exceptional_future<void>(
2234+ RemoteCommsException(string("failed to download from onedrive: ") + error_str));
2235+ });
2236+}
2237+
2238+boost::future<tuple<bool, string>> OnedriveDownloadJob::download_data()
2239+{
2240+ auto prom = boost::make_shared<boost::promise<tuple<bool, string>>>();
2241+
2242+ return boost::async([this, prom](){
2243+ std::lock_guard<std::mutex> guard(mutex_);
2244+
2245+ int socket_fd = write_socket();
2246+ DownloadBufferList buffer_item_list{{item_id_,
2247+ [socket_fd](void *dest, size_t buf_size) -> size_t {
2248+ //data writing callback.
2249+ return write(socket_fd, dest, buf_size);
2250+ }
2251+ }};
2252+
2253+ try {
2254+ task_ = client_->syncmanager()->add_download_tasks(buffer_item_list)[0];
2255+ task_->status_changed() = [this, prom](Task::Status status) {
2256+ std::cout << " status: " << status_to_string(status) << std::endl;
2257+ if (status == Task::Status::Complete) {
2258+ report_complete();
2259+ prom->set_value(make_tuple(true, string()));
2260+ } else if (status == Task::Status::Canceled ||
2261+ status == Task::Status::Broken) {
2262+ prom->set_value(make_tuple(false, task_->error_string()));
2263+ }
2264+ };
2265+ task_->progress_changed() = [this](float percent) {
2266+ cout<< "downloading: " << task_->content_name() << " " << percent << endl;
2267+ };
2268+ } catch (runtime_error & e) {
2269+ prom->set_value(make_tuple(false, e.what()));
2270+ }
2271+
2272+ return prom->get_future();
2273+ });
2274+}
2275+
2276+void OnedriveDownloadJob::stop_and_cancel()
2277+{
2278+ std::lock_guard<std::mutex> guard(mutex_);
2279+
2280+ if (task_ != nullptr &&
2281+ (task_->status() != Task::Status::Broken &&
2282+ task_->status() != Task::Status::Complete)) {
2283+ task_->cancel();
2284+ }
2285+}
2286+
2287+int main(int argc, char **argv)
2288+{
2289+ const std::string bus_name = "com.canonical.StorageFramework.Provider.OnedriveProvider";
2290+ std::string account_service_id = "com.canonical.scopes.onedrive_onedrive_onedrive";
2291+ if (argc > 1)
2292+ {
2293+ account_service_id = argv[1];
2294+ }
2295+
2296+ Server<OnedriveProvider> server(bus_name, account_service_id);
2297+ server.init(argc, argv);
2298+ server.run();
2299+}
2300
2301=== added file 'provider/OnedriveProvider.h'
2302--- provider/OnedriveProvider.h 1970-01-01 00:00:00 +0000
2303+++ provider/OnedriveProvider.h 2016-09-30 08:26:58 +0000
2304@@ -0,0 +1,74 @@
2305+/*
2306+ * Copyright (C) 2016 Canonical Ltd
2307+ *
2308+ * This program is free software: you can redistribute it and/or modify
2309+ * it under the terms of the GNU Lesser General Public License version 3 as
2310+ * published by the Free Software Foundation.
2311+ *
2312+ * This program is distributed in the hope that it will be useful,
2313+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2314+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2315+ * GNU Lesser General Public License for more details.
2316+ *
2317+ * You should have received a copy of the GNU Lesser General Public License
2318+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2319+ *
2320+ * Authors: Gary Wang <gary.wang@canonical.com>
2321+ */
2322+
2323+#pragma once
2324+
2325+#include <unity/storage/provider/ProviderBase.h>
2326+#include <onedrive/api/client.h>
2327+
2328+using namespace std;
2329+using namespace onedrive::api;
2330+using unity::storage::provider::Context;
2331+using unity::storage::provider::DownloadJob;
2332+using unity::storage::provider::ProviderBase;
2333+using unity::storage::provider::Item;
2334+using unity::storage::provider::ItemList;
2335+using unity::storage::provider::UploadJob;
2336+
2337+class OnedriveProvider : public ProviderBase {
2338+public:
2339+ OnedriveProvider();
2340+
2341+ boost::future<ItemList> roots(Context const& ctx) override;
2342+ boost::future<tuple<ItemList,string>> list(
2343+ string const& item_id, string const& page_token,
2344+ Context const& ctx) override;
2345+ boost::future<ItemList> lookup(
2346+ string const& parent_id, string const& name,
2347+ Context const& ctx) override;
2348+ boost::future<Item> metadata(
2349+ string const& item_id, Context const& ctx) override;
2350+ boost::future<Item> create_folder(
2351+ string const& parent_id, string const& name,
2352+ Context const& ctx) override;
2353+
2354+ boost::future<unique_ptr<UploadJob>> create_file(
2355+ string const& parent_id, string const& name,
2356+ int64_t size, string const& content_type, bool allow_overwrite,
2357+ Context const& ctx) override;
2358+ boost::future<unique_ptr<UploadJob>> update(
2359+ string const& item_id, int64_t size, string const& old_etag,
2360+ Context const& ctx) override;
2361+
2362+ boost::future<unique_ptr<DownloadJob>> download(
2363+ string const& item_id, Context const& ctx) override;
2364+
2365+ boost::future<void> delete_item(
2366+ string const& item_id, Context const& ctx) override;
2367+ boost::future<Item> move(
2368+ string const& item_id, string const& new_parent_id,
2369+ string const& new_name, Context const& ctx) override;
2370+ boost::future<Item> copy(
2371+ string const& item_id, string const& new_parent_id,
2372+ string const& new_name, Context const& ctx) override;
2373+
2374+private:
2375+ void set_access_token(Context const& ctx);
2376+private:
2377+ Client::Ptr client_;
2378+};
2379
2380=== added file 'provider/com.canonical.StorageFramework.Provider.OnedriveProvider.service'
2381--- provider/com.canonical.StorageFramework.Provider.OnedriveProvider.service 1970-01-01 00:00:00 +0000
2382+++ provider/com.canonical.StorageFramework.Provider.OnedriveProvider.service 2016-09-30 08:26:58 +0000
2383@@ -0,0 +1,3 @@
2384+[D-BUS Service]
2385+Name=com.canonical.StorageFramework.Provider.OnedriveProvider
2386+Exec=/usr/bin/onedrive-provider
2387
2388=== modified file 'src/CMakeLists.txt'
2389--- src/CMakeLists.txt 2016-09-26 04:27:03 +0000
2390+++ src/CMakeLists.txt 2016-09-30 08:26:58 +0000
2391@@ -17,10 +17,53 @@
2392 find_package(Boost COMPONENTS regex filesystem system REQUIRED)
2393 find_package(PkgConfig REQUIRED)
2394
2395-include_directories(${Boost_INCLUDE_DIRS} ${NET_CPP_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIRS})
2396-
2397 pkg_check_modules(JSON_CPP jsoncpp REQUIRED)
2398 pkg_check_modules(NET_CPP net-cpp>=1.3.0 REQUIRED)
2399-pkg_check_modules(PROCESS_CPP process-cpp REQUIRED)
2400+
2401+include_directories(${Boost_INCLUDE_DIRS} ${JSON_CPP_INCLUDE_DIRS} ${NET_CPP_INCLUDE_DIRS})
2402+
2403+add_library(
2404+ onedrive-provider SHARED
2405+
2406+ ${ONEDRIVE_PROVIDER_LIB_INTERFACE_HEADERS}
2407+
2408+ onedrive/api/client.cpp
2409+ onedrive/api/client_priv.cpp
2410+ onedrive/api/cloudfolder.cpp
2411+ onedrive/api/clouditem.cpp
2412+ onedrive/api/downloadtask.cpp
2413+ onedrive/api/downloadtask_priv.cpp
2414+ onedrive/api/uploadtask.cpp
2415+ onedrive/api/uploadtask_priv.cpp
2416+ onedrive/api/syncmanager.cpp
2417+ onedrive/api/syncmanager_priv.cpp
2418+ onedrive/api/syncthread.cpp
2419+ onedrive/api/storageinfo.cpp
2420+ onedrive/api/client.cpp
2421+)
2422+
2423+target_link_libraries(
2424+ onedrive-provider
2425+
2426+ ${CMAKE_THREAD_LIBS_INIT}
2427+
2428+ ${Boost_LIBRARIES}
2429+ ${JSON_CPP_LIBRARIES}
2430+ ${NET_CPP_LDFLAGS}
2431+)
2432
2433 set(symbol_map "${CMAKE_SOURCE_DIR}/symbols.map")
2434+set_target_properties(
2435+ onedrive-provider
2436+
2437+ PROPERTIES
2438+ LINK_FLAGS "${ldflags} -Wl,--version-script,${symbol_map}"
2439+ LINK_DEPENDS ${symbol_map}
2440+ VERSION ${ONEDRIVE_PROVIDER_LIB_VERSION_MAJOR}.${ONEDRIVE_PROVIDER_LIB_VERSION_MINOR}.${ONEDRIVE_PROVIDER_LIB_VERSION_PATCH}
2441+ SOVERSION ${ONEDRIVE_PROVIDER_LIB_VERSION_MAJOR}
2442+)
2443+
2444+install(
2445+ TARGETS onedrive-provider
2446+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
2447+)
2448
2449=== added file 'src/onedrive/api/client.cpp'
2450--- src/onedrive/api/client.cpp 1970-01-01 00:00:00 +0000
2451+++ src/onedrive/api/client.cpp 2016-09-30 08:26:58 +0000
2452@@ -0,0 +1,106 @@
2453+/*
2454+ * Copyright © 2016 Canonical Ltd.
2455+ *
2456+ * This program is free software: you can redistribute it and/or modify it
2457+ * under the terms of the GNU Lesser General Public License version 3,
2458+ * as published by the Free Software Foundation.
2459+ *
2460+ * This program is distributed in the hope that it will be useful,
2461+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2462+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2463+ * GNU Lesser General Public License for more details.
2464+ *
2465+ * You should have received a copy of the GNU Lesser General Public License
2466+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2467+ *
2468+ * Authored by: Gary Wang <gary.wang@canonical.com>
2469+ */
2470+
2471+#include <onedrive/api/client.h>
2472+#include "client_priv.h"
2473+
2474+#include <core/net/error.h>
2475+#include <core/net/uri.h>
2476+#include <core/net/http/client.h>
2477+#include <core/net/http/request.h>
2478+#include <core/net/http/response.h>
2479+
2480+#include <boost/filesystem.hpp>
2481+#include <boost/algorithm/string.hpp>
2482+
2483+using namespace onedrive::api;
2484+using namespace std;
2485+
2486+Client::Client(int request_timeout)
2487+ : p(std::make_shared<ClientPriv>(request_timeout)) {
2488+
2489+}
2490+
2491+Client::~Client() {
2492+ p->sync_manager()->cancel();
2493+}
2494+
2495+void Client::set_access_token(const string &access_token) {
2496+ p->set_access_token(access_token);
2497+// p->sync_manager()-
2498+}
2499+
2500+StorageInfo Client::storage_info() {
2501+ return p->storage_info();
2502+}
2503+
2504+CloudFolder::Ptr Client::root_folder() {
2505+ return p->root_folder();
2506+}
2507+
2508+tuple<Client::ResourceList, string> Client::cloud_content_list(const std::string &folder_id,
2509+ const std::string &page_token) {
2510+ return p->cloud_content_list(folder_id, page_token);
2511+}
2512+
2513+CloudResource::Ptr Client::metadata(const string &content_id) {
2514+ return p->metadata(content_id);
2515+}
2516+
2517+CloudFolder::Ptr Client::create_folder(const string &folder_name,
2518+ const string &folder_id) {
2519+ return p->create_folder(folder_name, folder_id);
2520+}
2521+
2522+Client::ResourceList Client::search(const string &name,
2523+ const string &parent_folder_id) {
2524+ return p->search(name, parent_folder_id);
2525+}
2526+
2527+CloudResource::Ptr Client::move_item(const std::string &item_id,
2528+ const std::string &folder_id,
2529+ const std::string &item_name) {
2530+ return p->move_item(item_id, folder_id, item_name);
2531+}
2532+
2533+bool Client::delete_item(const string &content_id) {
2534+ return p->delete_item(content_id);
2535+}
2536+
2537+/*
2538+CloudResource::Ptr Client::copy_item(const string &item_id,
2539+ const string &name,
2540+ const string &folder_id) {
2541+ return p->copy_item(item_id, name, folder_id);
2542+}
2543+*/
2544+
2545+CloudResource::Ptr Client::rename_item(const string &item_id,
2546+ const string &name) {
2547+ return p->rename_item(item_id, name);
2548+}
2549+
2550+//bool Client::refresh_token(const string &refresh_token) {
2551+// return p->refersh_token(refresh_token);
2552+//}
2553+
2554+SyncManager::Ptr Client::syncmanager() const {
2555+ return p->sync_manager();
2556+}
2557+
2558+
2559
2560=== added file 'src/onedrive/api/client_priv.cpp'
2561--- src/onedrive/api/client_priv.cpp 1970-01-01 00:00:00 +0000
2562+++ src/onedrive/api/client_priv.cpp 2016-09-30 08:26:58 +0000
2563@@ -0,0 +1,780 @@
2564+/*
2565+ * Copyright © 2016 Canonical Ltd.
2566+ *
2567+ * This program is free software: you can redistribute it and/or modify it
2568+ * under the terms of the GNU Lesser General Public License version 3,
2569+ * as published by the Free Software Foundation.
2570+ *
2571+ * This program is distributed in the hope that it will be useful,
2572+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2573+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2574+ * GNU Lesser General Public License for more details.
2575+ *
2576+ * You should have received a copy of the GNU Lesser General Public License
2577+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2578+ *
2579+ * Authored by: Gary Wang <gary.wang@canonical.com>
2580+ */
2581+
2582+#include "client_priv.h"
2583+#include "syncmanager_priv.h"
2584+#include "config.h"
2585+
2586+#include <onedrive/api/cloudfolder.h>
2587+#include <onedrive/api/clouditem.h>
2588+#include <onedrive/api/storageinfo.h>
2589+#include <onedrive/api/downloadtask.h>
2590+#include <onedrive/api/uploadtask.h>
2591+#include <onedrive/api/cloudresource.h>
2592+#include <onedrive/api/syncmanager.h>
2593+#include <onedrive/api/exceptions.h>
2594+
2595+#include <core/net/error.h>
2596+#include <core/net/uri.h>
2597+#include <core/net/http/client.h>
2598+#include <core/net/http/request.h>
2599+#include <core/net/http/response.h>
2600+
2601+#include <boost/algorithm/string.hpp>
2602+#include <boost/algorithm/string/regex.hpp>
2603+#include <boost/filesystem.hpp>
2604+#include <boost/regex.hpp>
2605+
2606+#include <json/json.h>
2607+
2608+#include <iostream>
2609+#include <unordered_map>
2610+
2611+namespace http = core::net::http;
2612+namespace json = Json;
2613+namespace net = core::net;
2614+
2615+namespace fs = boost::filesystem;
2616+namespace alg = boost::algorithm;
2617+
2618+using namespace onedrive::api;
2619+using namespace std;
2620+
2621+namespace {
2622+
2623+template<typename T>
2624+static void set_exception(std::shared_ptr<std::promise<T>> prom,
2625+ const json::Value &root) {
2626+ if (root.isMember("error")) {
2627+ std::string code = root["error"]["code"].asString();
2628+ std::string msg = root["error"]["message"].asString();
2629+ if (code == "unauthenticated") {
2630+ prom->set_exception(make_exception_ptr(CredentialException(msg)));
2631+ } else if (code == "itemNotFound") {
2632+ prom->set_exception(make_exception_ptr(NonExistentException(msg)));
2633+ } else if (code == "invalidRequest") {
2634+ prom->set_exception(make_exception_ptr(ParameterInvalidException(msg)));
2635+ } else if (code == "quotaLimitReached") {
2636+ prom->set_exception(make_exception_ptr(CredentialException(msg)));
2637+ } else if (code == "serviceNotAvailable") {
2638+ prom->set_exception(make_exception_ptr(ServiceNotAvailableException(msg)));
2639+ }
2640+
2641+ return;
2642+ }
2643+
2644+ prom->set_exception(make_exception_ptr(UnknownException(root.toStyledString())));
2645+}
2646+
2647+}
2648+
2649+class ClientPriv::HttpClient {
2650+public:
2651+ HttpClient(int request_timeout) :
2652+ client_(http::make_client()),
2653+ worker_ { [this]() {client_->run();} },
2654+ cancelled_(false) {
2655+ config_.request_timeout = request_timeout;
2656+ }
2657+
2658+ ~HttpClient() {
2659+ client_->stop();
2660+ if (worker_.joinable()) {
2661+ worker_.join();
2662+ }
2663+ }
2664+
2665+ std::shared_ptr<core::net::http::Client> client_;
2666+
2667+ std::thread worker_;
2668+
2669+ Config config_;
2670+
2671+ std::mutex config_mutex_;
2672+
2673+ std::atomic<bool> cancelled_;
2674+
2675+ void get(const net::Uri::Path &path,
2676+ const net::Uri::QueryParameters &parameters,
2677+ http::Request::Handler &handler) {
2678+ auto configuration = net_config(path, parameters);
2679+ configuration.header.add("User-Agent", config_.user_agent);
2680+
2681+ auto request = client_->head(configuration);
2682+ request->async_execute(handler);
2683+ }
2684+
2685+ void post(const net::Uri::Path &path,
2686+ const net::Uri::QueryParameters &parameters,
2687+ const std::string &postbody,
2688+ const std::string &content_type,
2689+ http::Request::Handler &handler) {
2690+ std::lock_guard<std::mutex> lock(config_mutex_);
2691+ http::Request::Configuration configuration = net_config(path, parameters);
2692+ configuration.header.add("User-Agent", config_.user_agent);
2693+ configuration.header.add("Content-Length", std::to_string(postbody.size()));
2694+ configuration.header.add("Content-Type", content_type);
2695+ configuration.header.add("Prefer", "respond-async");
2696+
2697+ auto request = client_->post(configuration, postbody, content_type);
2698+ request->async_execute(handler);
2699+ }
2700+
2701+ void del(const net::Uri::Path &path,
2702+ const net::Uri::QueryParameters &parameters,
2703+ http::Request::Handler &handler) {
2704+ std::lock_guard<std::mutex> lock(config_mutex_);
2705+ http::Request::Configuration configuration = net_config(path, parameters);
2706+ configuration.header.add("User-Agent", config_.user_agent);
2707+
2708+ auto request = client_->del(configuration);
2709+ request->async_execute(handler);
2710+ }
2711+
2712+ void patch(const net::Uri::Path &path,
2713+ const net::Uri::QueryParameters &parameters,
2714+ const std::string &postbody,
2715+ const std::string &content_type,
2716+ http::Request::Handler &handler) {
2717+ std::lock_guard<std::mutex> lock(config_mutex_);
2718+ http::Request::Configuration configuration = net_config(path, parameters);
2719+ configuration.header.add("User-Agent", config_.user_agent);
2720+ configuration.header.add("Content-Type", content_type);
2721+ //WORKAROUND: net-cpp doesn't support PATCH method.
2722+ configuration.header.add("X-HTTP-Method-Override", "PATCH");
2723+
2724+ auto request = client_->post(configuration, postbody, content_type);
2725+ request->async_execute(handler);
2726+ }
2727+
2728+ http::Request::Configuration net_config(const net::Uri::Path &path,
2729+ const net::Uri::QueryParameters &parameters) {
2730+ http::Request::Configuration configuration;
2731+ net::Uri::QueryParameters complete_parameters(parameters);
2732+ if (!config_.access_token.empty()) {
2733+ configuration.header.add("Authorization",
2734+ "bearer " + config_.access_token);
2735+ }
2736+
2737+ if (getenv("ONEDRIVE_LOCAL_SERVER_URL")) {
2738+ config_.apiroot = string(getenv("ONEDRIVE_LOCAL_SERVER_URL"));
2739+ configuration.header.add("Authorization",
2740+ "bearer " + config_.access_token);
2741+ }
2742+
2743+ net::Uri uri = net::make_uri(config_.apiroot, path,
2744+ complete_parameters);
2745+ configuration.uri = client_->uri_to_string(uri);
2746+ std::cout << "uri: "<<configuration.uri << std::endl;
2747+
2748+ return configuration;
2749+ }
2750+
2751+ http::Request::Progress::Next progress_changed(
2752+ const http::Request::Progress&) {
2753+ return cancelled_ ?
2754+ http::Request::Progress::Next::abort_operation :
2755+ http::Request::Progress::Next::continue_operation;
2756+ }
2757+
2758+ template<typename T>
2759+ future<T> async_get(const net::Uri::Path &path,
2760+ const net::Uri::QueryParameters &parameters,
2761+ const function<T(const json::Value &root)> &func) {
2762+ auto prom = make_shared<promise<T>>();
2763+
2764+ http::Request::Handler handler;
2765+ handler.on_progress(
2766+ bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1));
2767+ handler.on_error([prom](const net::Error& e)
2768+ {
2769+ prom->set_exception(make_exception_ptr(runtime_error(e.what())));
2770+ });
2771+ handler.on_response(
2772+ [prom,func](const http::Response& response)
2773+ {
2774+ json::Reader reader;
2775+ json::Value root;
2776+
2777+ std::cout <<"http status code: " << response.status <<"response.body: " << response.body
2778+ << std::endl;
2779+
2780+ //for download link generation, link can be found at header[location] according to dev doc
2781+ if (response.status == net::http::Status::accepted) {
2782+ response.header.enumerate([&root](const std::string& key,
2783+ const std::set<std::string>& /*values*/) {
2784+ vector<string> headers;
2785+ boost::split_regex(headers, key, boost::regex(": "));
2786+ boost::trim_right(headers[1]);
2787+ root[headers[0]] = headers[1];
2788+ std::cout << "header: " << key <<" " << headers[1] << std::endl;
2789+ });
2790+ prom->set_value(func(root));
2791+ } else if (!reader.parse(response.body, root)) {
2792+ prom->set_exception(make_exception_ptr(UnknownException("json parse failed")));
2793+ } else {
2794+ if (response.status != net::http::Status::ok) {
2795+ set_exception<T>(prom, root);
2796+ } else {
2797+ prom->set_value(func(root));
2798+ }
2799+ }
2800+ }
2801+ );
2802+
2803+ get(path, parameters, handler);
2804+
2805+ return prom->get_future();
2806+ }
2807+
2808+ template<typename T>
2809+ future<T> async_post(const net::Uri::Path &path,
2810+ const net::Uri::QueryParameters &parameters,
2811+ const std::string &postmsg,
2812+ const std::string &content_type,
2813+ const function<T(const json::Value &root)> &func) {
2814+ auto prom = make_shared<promise<T>>();
2815+
2816+ http::Request::Handler handler;
2817+ handler.on_progress(
2818+ bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1));
2819+ handler.on_error([prom](const net::Error& e)
2820+ {
2821+ prom->set_exception(make_exception_ptr(runtime_error(e.what())));
2822+ });
2823+ handler.on_response(
2824+ [path, prom,func](const http::Response& response)
2825+ {
2826+ json::Reader reader;
2827+ json::Value root;
2828+
2829+ std::cout <<"http status code: " << response.status <<"response.body: " << response.body
2830+ <<" isempty: " <<response.body.empty() << std::endl;
2831+
2832+ if (!reader.parse(response.body, root)) {
2833+ prom->set_exception(make_exception_ptr(runtime_error("json parse failed")));
2834+ } else if (response.status != net::http::Status::ok &&
2835+ response.status != net::http::Status::created &&
2836+ response.status != net::http::Status::accepted &&
2837+ response.status != net::http::Status::see_other) {
2838+ set_exception<T>(prom, root);
2839+ } else {
2840+ //To deal with AsyncJobStatus
2841+ //https://dev.onedrive.com/items/copy.htm
2842+ string cache_header;
2843+ if (response.status == net::http::Status::accepted) {
2844+ json::Value requestJson;
2845+ json::StyledWriter writer;
2846+ response.header.enumerate([&requestJson, &cache_header,
2847+ &writer](const std::string& key,
2848+ const std::set<std::string>& /*values*/) {
2849+ vector<string> headers;
2850+ boost::split_regex(headers, key, boost::regex(": "));
2851+ boost::trim_right(headers[1]);
2852+ requestJson[headers[0]] = headers[1];
2853+ std::cout << "sdfsdfsd: " << key <<" " << headers[1] << std::endl;
2854+ });
2855+
2856+ cache_header = writer.write(requestJson);
2857+// return;
2858+ }
2859+
2860+ if (!cache_header.empty() && !reader.parse(cache_header, root)) {
2861+ prom->set_exception(make_exception_ptr(runtime_error("json parse failed")));
2862+ } else {
2863+ prom->set_value(func(root));
2864+ }
2865+ }
2866+ }
2867+ );
2868+
2869+ post(path, parameters, postmsg, content_type, handler);
2870+
2871+ return prom->get_future();
2872+ }
2873+
2874+ template<typename T>
2875+ future<T> async_patch(const net::Uri::Path &path,
2876+ const net::Uri::QueryParameters &parameters,
2877+ const std::string &postmsg,
2878+ const std::string &content_type,
2879+ const function<T(const json::Value &root)> &func) {
2880+ auto prom = make_shared<promise<T>>();
2881+
2882+ http::Request::Handler handler;
2883+ handler.on_progress(
2884+ bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1));
2885+ handler.on_error([prom](const net::Error& e)
2886+ {
2887+ prom->set_exception(make_exception_ptr(runtime_error(e.what())));
2888+ });
2889+ handler.on_response(
2890+ [path, prom,func](const http::Response& response)
2891+ {
2892+ json::Reader reader;
2893+ json::Value root;
2894+
2895+ std::cout <<"http status code: " << response.status <<"response.body: " << response.body
2896+ <<" isempty: " <<response.body.empty() << std::endl;
2897+
2898+ if (!reader.parse(response.body, root)) {
2899+ prom->set_exception(make_exception_ptr(UnknownException("json parse failed")));
2900+ } else {
2901+ if (response.status != net::http::Status::ok) {
2902+ set_exception<T>(prom, root);
2903+ } else {
2904+ prom->set_value(func(root));
2905+ }
2906+ }
2907+ }
2908+ );
2909+
2910+ patch(path, parameters, postmsg, content_type, handler);
2911+
2912+ return prom->get_future();
2913+ }
2914+
2915+ template<typename T>
2916+ future<T> async_del(const net::Uri::Path &path,
2917+ const net::Uri::QueryParameters &parameters,
2918+ const function<T(const json::Value &root)> &func) {
2919+ auto prom = make_shared<promise<T>>();
2920+
2921+ http::Request::Handler handler;
2922+ handler.on_progress(
2923+ bind(&ClientPriv::HttpClient::progress_changed, this, placeholders::_1));
2924+ handler.on_error([prom](const net::Error& e)
2925+ {
2926+ prom->set_exception(make_exception_ptr(runtime_error(e.what())));
2927+ });
2928+ handler.on_response(
2929+ [prom,func](const http::Response& response)
2930+ {
2931+ std::cout <<"http status code: " << response.status <<"response.body: " << response.body
2932+ << std::endl;
2933+
2934+ json::Reader reader;
2935+ json::Value root;
2936+ if (response.status == net::http::Status::no_content) {
2937+ prom->set_value(func(root));
2938+ } else {
2939+ if (!reader.parse(response.body, root)) {
2940+ prom->set_exception(make_exception_ptr(UnknownException("json parse failed")));
2941+ } else{
2942+ set_exception<T>(prom, root);
2943+ }
2944+ }
2945+ }
2946+ );
2947+
2948+ del(path, parameters, handler);
2949+
2950+ return prom->get_future();
2951+ }
2952+};
2953+
2954+ClientPriv::ClientPriv(int request_timeout)
2955+ : httpclient_(std::make_shared<HttpClient>(request_timeout))
2956+ , sync_manager_(std::shared_ptr<SyncManager>(new SyncManager(this))) {
2957+}
2958+
2959+ClientPriv::~ClientPriv() {
2960+ httpclient_->cancelled_ = true;
2961+}
2962+
2963+void ClientPriv::set_access_token(const string &access_token) {
2964+ httpclient_->config_.access_token = access_token;
2965+ sync_manager_->p_->set_access_token(access_token);
2966+}
2967+
2968+StorageInfo ClientPriv::storage_info() {
2969+ auto storage_future = httpclient_->async_get<StorageInfo>(
2970+ { "drive" }, { },
2971+ [](const json::Value &root) {
2972+ return StorageInfo(root);
2973+ });
2974+
2975+ return get_or_throw(storage_future);
2976+}
2977+
2978+CloudResource::Ptr ClientPriv::metadata(const string &content_id) {
2979+ auto disk_future = httpclient_->async_get<CloudResource::Ptr>(
2980+ { "drive", "items", content_id }, { },
2981+ [](const json::Value &root) -> CloudResource::Ptr {
2982+ if (root.isMember("folder"))
2983+ return shared_ptr<CloudFolder>(new CloudFolder(root));
2984+ return shared_ptr<CloudItem>(new CloudItem(root));
2985+ });
2986+
2987+ return get_or_throw(disk_future);
2988+}
2989+
2990+CloudFolder::Ptr ClientPriv::root_folder() {
2991+ auto folder_future = httpclient_->async_get<CloudFolder::Ptr>(
2992+ { "drive", "items", "root" }, { },
2993+ [](const json::Value &root) -> CloudFolder::Ptr {
2994+ return shared_ptr<CloudFolder>(new CloudFolder(root));
2995+ });
2996+
2997+ return get_or_throw(folder_future);
2998+}
2999+
3000+tuple<Client::ResourceList, string> ClientPriv::cloud_content_list(const std::string &folder_id,
3001+ const std::string &page_token) {
3002+ net::Uri::Path path { "drive", "items" };
3003+ if (folder_id.empty()) {
3004+ path.emplace_back("root");
3005+ } else {
3006+ path.emplace_back(folder_id);
3007+ }
3008+
3009+ net::Uri::QueryParameters params { { "expand", "children" } };
3010+ if (!page_token.empty()) {
3011+ params.emplace_back(make_pair("skiptoken", page_token));
3012+ }
3013+
3014+ auto resource_future = httpclient_->async_get<tuple<Client::ResourceList, string>>(
3015+ path, params,
3016+ [](const json::Value &root) -> tuple<Client::ResourceList, string> {
3017+ Client::ResourceList results;
3018+
3019+ json::Value children;
3020+ if (root.isMember("children"))
3021+ children = root["children"];
3022+ else if (root.isMember("value"))
3023+ children = root["value"];
3024+
3025+ for (const auto & child: children) {
3026+ if (child.isMember("folder")) {
3027+ results.push_back(std::shared_ptr<CloudFolder>(new CloudFolder(child)));
3028+ } else {
3029+ results.push_back(std::shared_ptr<CloudItem>(new CloudItem(child)));
3030+ }
3031+ }
3032+
3033+ string next_page_token;
3034+ if (root.isMember("children@odata.nextLink")) {
3035+ const string nextToken = "skiptoken";
3036+ string nextLink = root["children@odata.nextLink"].asString();
3037+ size_t pos = nextLink.find(nextToken) + nextToken.length();
3038+ next_page_token = nextLink.substr(pos);
3039+ }
3040+
3041+ return make_tuple(results, next_page_token);
3042+ });
3043+
3044+ return get_or_throw(resource_future);
3045+}
3046+
3047+Client::ResourceList ClientPriv::search(const string &name,
3048+ const string &folder_id) {
3049+ net::Uri::Path path { "drive", "items" };
3050+ if (folder_id.empty()) {
3051+ path.emplace_back("root");
3052+ } else {
3053+ path.emplace_back(folder_id);
3054+ }
3055+ path.emplace_back("view.search");
3056+
3057+ auto resource_future = httpclient_->async_get<Client::ResourceList>(
3058+ path, {{"q", name}},
3059+ [](const json::Value &root) -> Client::ResourceList {
3060+ Client::ResourceList results;
3061+
3062+ json::Value children;
3063+ if (root.isMember("children"))
3064+ children = root["children"];
3065+ else if (root.isMember("value"))
3066+ children = root["value"];
3067+ for (const auto & child: children) {
3068+ if (child.isMember("folder")) {
3069+ results.push_back(std::shared_ptr<CloudFolder>(new CloudFolder(child)));
3070+ } else {
3071+ results.push_back(std::shared_ptr<CloudItem>(new CloudItem(child)));
3072+ }
3073+ }
3074+
3075+ return results;
3076+ });
3077+
3078+ return get_or_throw(resource_future);
3079+}
3080+
3081+CloudFolder::Ptr ClientPriv::create_folder(const string &folder_name,
3082+ const string &folder_id) {
3083+ net::Uri::Path path { "drive", "items" };
3084+ if (folder_id.empty()) {
3085+ path.emplace_back("root");
3086+ } else {
3087+ path.emplace_back(folder_id);
3088+ }
3089+ path.emplace_back("children");
3090+
3091+ json::Value requestJson;
3092+ requestJson["name"] = folder_name;
3093+ requestJson["folder"] = json::Value(json::objectValue);
3094+
3095+ json::StyledWriter writer;
3096+ std::string postbody = writer.write( requestJson );
3097+ std::string content_type = "application/json";
3098+ std::cout << "postbody: " << postbody << std::endl;
3099+
3100+ auto created = httpclient_->async_post<CloudFolder::Ptr>(path,
3101+ { }, postbody, content_type,
3102+ [](const json::Value &root) -> CloudFolder::Ptr {
3103+ return shared_ptr<CloudFolder>(new CloudFolder(root));
3104+ });
3105+
3106+ return get_or_throw(created);
3107+}
3108+
3109+bool ClientPriv::delete_item(const string item_id) {
3110+ auto del = httpclient_->async_del<bool>(
3111+ { "drive", "items", item_id }, { },
3112+ [](const json::Value &root) -> bool {
3113+ return root.isNull() ? true : false;
3114+ });
3115+
3116+ return get_or_throw(del);
3117+}
3118+
3119+/*
3120+CloudResource::Ptr ClientPriv::copy_item(const std::string &item_id,
3121+ const std::string &item_name,
3122+ const std::string &folder_id) {
3123+ json::Value requestJson;
3124+ requestJson["parentReference"]["id"] = folder_id;
3125+ requestJson["name"] = item_name;
3126+
3127+ json::StyledWriter writer;
3128+ std::string postbody = writer.write( requestJson );
3129+ std::string content_type = "application/json";
3130+ std::cout << "postbody: " << postbody << std::endl;
3131+
3132+ auto copy = httpclient_->async_post<unordered_map<string, string>>(
3133+ { "drive", "items", item_id, "action.copy"}, { }, postbody, content_type,
3134+ [](const json::Value &root) -> unordered_map<string, string> {
3135+ unordered_map<string, string> map{
3136+ {"Content-Length", root["Content-Length"].asString()},
3137+ {"Location", root["Location"].asString()},
3138+ {"Preference-Applied", root["Preference-Applied"].asString()},
3139+ {"Server", root["Preference-Applied"].asString()},
3140+ {"X-Msnserver", root["X-Msnserver"].asString()},
3141+ {"X-Wlsproxy", root["X-Wlsproxy"].asString()}
3142+ };
3143+ return map;
3144+ });
3145+
3146+ auto cache_header = get_or_throw(copy);
3147+ for (const auto & c: cache_header) {
3148+ std::cout << c.first << " "<< c.second << std::endl;
3149+ }
3150+
3151+ auto ePos = cache_header["Location"].find_last_of('/');
3152+ auto sub_path = cache_header["Location"].substr(ePos + 1);
3153+
3154+ std::cout << "cache_header.size():" << cache_header.size() << " "<< cache_header["Location"] << " "
3155+ << sub_path << std::endl;
3156+ if (!cache_header.empty()) {
3157+ auto check_future = httpclient_->async_get<CloudResource::Ptr>(
3158+ { "monitor", sub_path}, { }, cache_header,
3159+ [](const json::Value &root) -> CloudResource::Ptr {
3160+ return root.isNull()? nullptr : nullptr;
3161+ });
3162+
3163+ CloudResource::Ptr ptr = get_or_throw(check_future);
3164+ Client::ResourceList resourceList = search(item_name, folder_id);
3165+ if (resourceList.size() > 0)
3166+ return resourceList[0];
3167+ }
3168+
3169+ throw runtime_error("item copy failed");
3170+}
3171+*/
3172+
3173+
3174+CloudResource::Ptr ClientPriv::move_item(const std::string &item_id,
3175+ const std::string &folder_id,
3176+ const std::string &item_name) {
3177+ json::Value requestJson;
3178+ requestJson["parentReference"]["id"] = folder_id;
3179+ if (!item_name.empty())
3180+ requestJson["name"] = item_name;
3181+
3182+ json::StyledWriter writer;
3183+ std::string postbody = writer.write(requestJson);
3184+ std::string content_type = "application/json";
3185+
3186+ auto move_future = httpclient_->async_patch<CloudResource::Ptr>(
3187+ { "drive", "items", item_id }, { },postbody, content_type,
3188+ [](const json::Value &root) -> CloudResource::Ptr {
3189+ if (root.isMember("folder"))
3190+ return shared_ptr<CloudFolder>(new CloudFolder(root));
3191+ return shared_ptr<CloudItem>(new CloudItem(root));
3192+ });
3193+
3194+ return get_or_throw(move_future);
3195+}
3196+
3197+CloudResource::Ptr ClientPriv::rename_item(const string &item_id, const string &new_name) {
3198+ json::Value requestJson;
3199+ requestJson["name"] = new_name;
3200+
3201+ json::StyledWriter writer;
3202+ std::string postbody = writer.write(requestJson);
3203+ std::string content_type = "application/json";
3204+
3205+ auto move_future = httpclient_->async_patch<CloudResource::Ptr>(
3206+ { "drive", "items", item_id }, { }, postbody, content_type,
3207+ [](const json::Value &root) -> CloudResource::Ptr {
3208+ if (root.isMember("folder"))
3209+ return shared_ptr<CloudFolder>(new CloudFolder(root));
3210+ return shared_ptr<CloudItem>(new CloudItem(root));
3211+ });
3212+
3213+ return get_or_throw(move_future);
3214+}
3215+
3216+string ClientPriv::request_download_link(const string &item_id) {
3217+ auto link_future = httpclient_->async_get<string>(
3218+ { "drive", "items", item_id, "content" }, { },
3219+ [](const json::Value &root) -> string {
3220+ return root["location"].asString();
3221+ });
3222+
3223+ return get_or_throw(link_future);
3224+}
3225+
3226+//DownloadTaskPriv::Ptr ClientPriv::request_download_link(const DownloadBuffer &buffer_item) {
3227+
3228+//}
3229+
3230+/*
3231+SyncManager::UploadList ClientPriv::create_upload_link(const UploadRequest &request_item) {
3232+ if (!fs::exists(request_item.file_path))
3233+ throw std::runtime_error(string("file not exists: ").append(request_item.file_path));
3234+
3235+ string postbody = generate_upload_body(request_item);
3236+
3237+ log(postbody);
3238+
3239+ auto future = httpclient_->async_post<SyncManager::UploadList>(
3240+ { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
3241+ [request_item](const tinyxml2::XMLElement *root) {
3242+ SyncManager::UploadList results;
3243+
3244+ auto upload_res = root->FirstChildElement("uploadResult");
3245+ std::string task_id = upload_res->FirstChildElement("uploadTaskID")->GetText();
3246+
3247+ std::string redirection_url;
3248+ if (upload_res->FirstChildElement("redirectionUrl")) {
3249+ redirection_url = upload_res->FirstChildElement("redirectionUrl")->GetText();
3250+ }
3251+
3252+ auto content_list = upload_res->FirstChildElement("newContentIDList");
3253+ if (content_list) {
3254+ auto content = content_list->FirstChildElement();
3255+ while(content) {
3256+ results.push(std::shared_ptr<UploadTask>(new UploadTask(content,
3257+ task_id,
3258+ redirection_url,
3259+ request_item.file_path)));
3260+ content = content->NextSiblingElement();
3261+ }
3262+ }
3263+
3264+ return results;
3265+ });
3266+
3267+ return get_or_throw(future);
3268+}
3269+
3270+SyncManager::UploadList ClientPriv::create_upload_link(const UploadBuffer &buffer_item) {
3271+ string postbody = generate_upload_body(buffer_item);
3272+
3273+ log(postbody);
3274+
3275+ auto future = httpclient_->async_post<SyncManager::UploadList>(
3276+ { "richlifeApp", "devapp", "IUploadAndDownload" }, { }, postbody, content_type,
3277+ [buffer_item](const tinyxml2::XMLElement *root) {
3278+ SyncManager::UploadList results;
3279+
3280+ auto upload_res = root->FirstChildElement("uploadResult");
3281+ std::string task_id = upload_res->FirstChildElement("uploadTaskID")->GetText();
3282+
3283+ std::string redirection_url;
3284+ if (upload_res->FirstChildElement("redirectionUrl")) {
3285+ redirection_url = upload_res->FirstChildElement("redirectionUrl")->GetText();
3286+ }
3287+
3288+ auto content_list = upload_res->FirstChildElement("newContentIDList");
3289+ if (content_list) {
3290+ auto content = content_list->FirstChildElement();
3291+ while(content) {
3292+ results.push(std::shared_ptr<UploadTask>(new UploadTask(content,
3293+ task_id,
3294+ redirection_url,
3295+ buffer_item.buffer_size,
3296+ buffer_item.read_cb)));
3297+ content = content->NextSiblingElement();
3298+ }
3299+ }
3300+
3301+ return results;
3302+ });
3303+
3304+ return get_or_throw(future);
3305+}
3306+
3307+bool ClientPriv::refersh_token(const string &refresh_token) {
3308+ const std::string content_type = "application/x-www-form-urlencoded";
3309+ const std::string postbody = "grant_type=refresh_token&refresh_token="
3310+ + refresh_token;
3311+ log(postbody);
3312+
3313+ auto future = httpclient_->async_post<bool>(
3314+ { "oauthApp", "OAuth2", "refreshToken" }, { }, postbody, content_type,
3315+ [this](const tinyxml2::XMLElement *root) {
3316+ boost::cmatch cap;
3317+ const boost::regex exp(".*\"(.*?)\"\\}");
3318+ if (boost::regex_match(root->GetText(), cap, exp)) {
3319+ httpclient_->config_.access_token = cap[1];
3320+ return true;
3321+ }
3322+ return false;
3323+ });
3324+
3325+ return get_or_throw(future);
3326+}
3327+*/
3328+
3329+void ClientPriv::cancel() {
3330+ httpclient_->cancelled_ = true;
3331+}
3332+
3333+SyncManager::Ptr ClientPriv::sync_manager() {
3334+ return sync_manager_;
3335+}
3336+
3337+template<typename T> T ClientPriv::get_or_throw(std::future<T> &f) {
3338+ if (f.wait_for(std::chrono::seconds(httpclient_->config_.request_timeout)) != std::future_status::ready) {
3339+ throw HttpTimeoutException("HTTP request timeout");
3340+ }
3341+
3342+ return f.get();
3343+}
3344
3345=== added file 'src/onedrive/api/client_priv.h'
3346--- src/onedrive/api/client_priv.h 1970-01-01 00:00:00 +0000
3347+++ src/onedrive/api/client_priv.h 2016-09-30 08:26:58 +0000
3348@@ -0,0 +1,106 @@
3349+/*
3350+ * Copyright (C) 2016 Canonical, Ltd.
3351+ *
3352+ * This library is free software; you can redistribute it and/or modify it under
3353+ * the terms of version 3 of the GNU Lesser General Public License as published
3354+ * by the Free Software Foundation.
3355+ *
3356+ * This library is distributed in the hope that it will be useful, but WITHOUT
3357+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3358+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
3359+ * details.
3360+ *
3361+ * You should have received a copy of the GNU Lesser General Public License
3362+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3363+ *
3364+ * Authored by: Gary Wang <gary.wang@canonical.com>
3365+ */
3366+
3367+#ifndef ONEDRIVE_API_CLIENTPRIV_H_
3368+#define ONEDRIVE_API_CLIENTPRIV_H_
3369+
3370+#include <onedrive/api/client.h>
3371+#include <onedrive/api/visibility.h>
3372+#include <onedrive/api/cloudresource.h>
3373+
3374+#include <future>
3375+#include <string>
3376+#include <memory>
3377+
3378+#include "downloadtask_priv.h"
3379+#include "uploadtask_priv.h"
3380+
3381+namespace onedrive {
3382+namespace api {
3383+
3384+class Client;
3385+
3386+class ONEDRIVE_API_DLL_LOCAL ClientPriv {
3387+ public:
3388+
3389+ enum class ServerCode {
3390+ };
3391+
3392+ typedef std::shared_ptr<ClientPriv> Ptr;
3393+
3394+ ClientPriv(int request_timeout = 10);
3395+
3396+ virtual ~ClientPriv();
3397+
3398+ StorageInfo storage_info();
3399+
3400+ void set_access_token(const std::string &access_token);
3401+
3402+// bool refersh_token(const std::string &refresh_token);
3403+
3404+ CloudResource::Ptr metadata(const std::string &content_id);
3405+
3406+ CloudFolder::Ptr root_folder();
3407+
3408+ std::tuple<Client::ResourceList, std::string> cloud_content_list(const std::string &folder_id = std::string(),
3409+ const std::string &page_token = std::string());
3410+
3411+ Client::ResourceList search(const std::string &name,
3412+ const std::string &folder_id);
3413+
3414+ CloudFolder::Ptr create_folder(const std::string &folder_name,
3415+ const std::string &folder_id);
3416+
3417+ /*
3418+ CloudResource::Ptr copy_item(const std::string &item_id,
3419+ const std::string &item_name,
3420+ const std::string &folder_id);
3421+ */
3422+
3423+ CloudResource::Ptr move_item(const std::string &item_id,
3424+ const std::string &folder_id,
3425+ const std::string &item_name);
3426+
3427+ CloudResource::Ptr rename_item(const std::string &item_id,
3428+ const std::string &new_name);
3429+
3430+
3431+ bool delete_item(const std::string item_id);
3432+
3433+ std::string request_download_link(const std::string &item_id);
3434+
3435+// DownloadTaskPriv::Ptr request_download_link(const DownloadBuffer &buffer_item);
3436+
3437+ void cancel();
3438+
3439+ std::shared_ptr<SyncManager> sync_manager();
3440+
3441+ private:
3442+ template<typename T> T get_or_throw(std::future<T> &f);
3443+
3444+ private:
3445+ class HttpClient;
3446+ std::shared_ptr<HttpClient> httpclient_;
3447+
3448+ std::shared_ptr<SyncManager> sync_manager_;
3449+};
3450+
3451+}
3452+}
3453+
3454+#endif // ONEDRIVE_API_CLIENTPRIV_H_
3455
3456=== added file 'src/onedrive/api/cloudfolder.cpp'
3457--- src/onedrive/api/cloudfolder.cpp 1970-01-01 00:00:00 +0000
3458+++ src/onedrive/api/cloudfolder.cpp 2016-09-30 08:26:58 +0000
3459@@ -0,0 +1,121 @@
3460+/*
3461+ * Copyright © 2016 Canonical Ltd.
3462+ *
3463+ * This program is free software: you can redistribute it and/or modify it
3464+ * under the terms of the GNU Lesser General Public License version 3,
3465+ * as published by the Free Software Foundation.
3466+ *
3467+ * This program is distributed in the hope that it will be useful,
3468+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3469+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3470+ * GNU Lesser General Public License for more details.
3471+ *
3472+ * You should have received a copy of the GNU Lesser General Public License
3473+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3474+ *
3475+ * Authored by: Gary Wang <gary.wang@canonical.com>
3476+ */
3477+
3478+#include <onedrive/api/cloudfolder.h>
3479+
3480+#include <json/json.h>
3481+
3482+#include <time.h>
3483+#include <iostream>
3484+#include <sstream>
3485+
3486+namespace json = Json;
3487+
3488+using namespace onedrive::api;
3489+using namespace std;
3490+
3491+std::time_t string_to_time(const std::string dt) {
3492+ struct std::tm tm;
3493+ std::istringstream ss(dt);
3494+ strptime(dt.c_str(), "%Y%m%d%H%M%S",&tm); // std::get std::put only available in GCC 5
3495+ return std::mktime(&tm);
3496+}
3497+
3498+class CloudFolder::Priv {
3499+public:
3500+ Priv(const json::Value &root) {
3501+ id_ = root["id"].asString();
3502+ updated_date_ = string_to_time(root["lastModifiedDateTime"].asString());
3503+ created_date_ = string_to_time(root["createdDateTime"].asString());
3504+ etag_ = root["eTag"].asString();
3505+ name_ = root["name"].asString();
3506+ owner_ = root["createdBy"]["user"]["displayName"].asString();
3507+ folder_id_ = root.isMember("parentReference")?
3508+ root["parentReference"]["id"].asString() : "";
3509+ children_count_ = root["folder"]["childCount"].asInt();
3510+
3511+ #ifndef NDEBUG
3512+ cout << "id: "<< id_ << " name: " << name_ << " etag: "<< etag_ << endl;
3513+ #endif
3514+
3515+ }
3516+
3517+ std::string id_;
3518+
3519+ std::string name_;
3520+
3521+ std::time_t created_date_;
3522+
3523+ std::time_t updated_date_;
3524+
3525+ std::string download_url_;
3526+
3527+ std::string folder_id_;
3528+
3529+ std::string etag_;
3530+
3531+ std::string owner_;
3532+
3533+ std::string folder_path_;
3534+
3535+ int children_count_;
3536+};
3537+
3538+CloudFolder::CloudFolder(const json::Value &root)
3539+ :p(std::make_shared<Priv>(root)){
3540+}
3541+
3542+const string &CloudFolder::id() const {
3543+ return p->id_;
3544+}
3545+
3546+const string &CloudFolder::name() const {
3547+ return p->name_;
3548+}
3549+
3550+const time_t &CloudFolder::created_date() const {
3551+ return p->created_date_;
3552+}
3553+
3554+const time_t &CloudFolder::updated_date() const {
3555+ return p->updated_date_;
3556+}
3557+
3558+const string &CloudFolder::download_url() const {
3559+ return p->download_url_;
3560+}
3561+
3562+const string &CloudFolder::folder_id() const {
3563+ return p->folder_id_;
3564+}
3565+
3566+const string &CloudFolder::folder_path() const {
3567+ return p->folder_path_;
3568+}
3569+
3570+const string &CloudFolder::etag() const {
3571+ return p->etag_;
3572+}
3573+
3574+const string &CloudFolder::owner() const {
3575+ return p->owner_;
3576+}
3577+
3578+CloudResource::Property CloudFolder::property() const {
3579+ return CloudResource::Property::Folder;
3580+}
3581
3582=== added file 'src/onedrive/api/clouditem.cpp'
3583--- src/onedrive/api/clouditem.cpp 1970-01-01 00:00:00 +0000
3584+++ src/onedrive/api/clouditem.cpp 2016-09-30 08:26:58 +0000
3585@@ -0,0 +1,166 @@
3586+/*
3587+ * Copyright © 2016 Canonical Ltd.
3588+ *
3589+ * This program is free software: you can redistribute it and/or modify it
3590+ * under the terms of the GNU Lesser General Public License version 3,
3591+ * as published by the Free Software Foundation.
3592+ *
3593+ * This program is distributed in the hope that it will be useful,
3594+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3595+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3596+ * GNU Lesser General Public License for more details.
3597+ *
3598+ * You should have received a copy of the GNU Lesser General Public License
3599+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3600+ *
3601+ * Authored by: Gary Wang <gary.wang@canonical.com>
3602+ */
3603+
3604+#include <onedrive/api/clouditem.h>
3605+#include <json/json.h>
3606+
3607+#include <iostream>
3608+
3609+namespace json = Json;
3610+
3611+using namespace onedrive::api;
3612+using namespace std;
3613+
3614+extern std::time_t string_to_time(const std::string dt);
3615+
3616+class CloudItem::Priv {
3617+public:
3618+ Priv(const json::Value &root) {
3619+ id_ = root["id"].asString();
3620+ updated_date_ = string_to_time(root["lastModifiedDateTime"].asString());
3621+ created_date_ = string_to_time(root["createdDateTime"].asString());
3622+ etag_ = root["eTag"].asString();
3623+ name_ = root["name"].asString();
3624+ owner_ = root["createdBy"]["user"]["displayName"].asString();
3625+ folder_id_ = root["parentReference"]["id"].asString();
3626+ mimetype_ = root["file"].isMember("mimeType") ? root["file"]["mimeType"].asString() : "";
3627+ content_size_ = root["size"].asInt64();
3628+ download_url_ = root["@content.downloadUrl"].asString();
3629+ folder_path_ = root["parentReference"]["path"].asString();
3630+
3631+ if (!mimetype_.empty()) {
3632+ if (mimetype_.find("video/") != string::npos) {
3633+ if (root.isMember("photo") && root["photo"].isMember("takenDateTime")) {
3634+ metadata_["takenDateTime"] = root["photo"]["takenDateTime"].asString();
3635+ }
3636+ metadata_["width"] = root["video"]["width"].asInt();
3637+ metadata_["height"] = root["video"]["height"].asInt();
3638+ metadata_["bitrate"] = root["video"]["bitrate"].asInt();
3639+ metadata_["duration"] = root["video"]["duration"].asInt();
3640+ } else if (mimetype_.find("audio/") != string::npos) {
3641+ metadata_["duration"] = root["duration"]["duration"].asUInt();
3642+ } else if (mimetype_.find("image/") != string::npos) {
3643+ metadata_["width"] = root["image"]["width"].asInt();
3644+ metadata_["height"] = root["image"]["height"].asInt();
3645+
3646+ if (root.isMember("photo")) {
3647+ if (root["photo"].isMember("cameraMake"))
3648+ metadata_["cameraMake"] = root["photo"]["cameraMake"].asString();
3649+ if (root["photo"].isMember("cameraModel"))
3650+ metadata_["cameraModel"] = root["photo"]["cameraModel"].asString();
3651+ if (root["photo"].isMember("exposureDenominator"))
3652+ metadata_["exposureDenominator"] = root["photo"]["exposureDenominator"].asInt();
3653+ if (root["photo"].isMember("exposureNumerator"))
3654+ metadata_["exposureNumerator"] = root["photo"]["exposureNumerator"].asInt();
3655+ if (root["photo"].isMember("fNumber"))
3656+ metadata_["fNumber"] = root["photo"]["fNumber"].asFloat();
3657+ if (root["photo"].isMember("iso"))
3658+ metadata_["iso"] = root["photo"]["iso"].asInt();
3659+ }
3660+ }
3661+ }
3662+ #ifndef NDEBUG
3663+ cout << "id: "<< id_ << " name: " << name_ << " etag: "<< etag_ << endl;
3664+ #endif
3665+ }
3666+
3667+ std::string id_;
3668+
3669+ std::string name_;
3670+
3671+ std::time_t created_date_;
3672+
3673+ std::time_t updated_date_;
3674+
3675+ std::string etag_;
3676+
3677+ std::string owner_;
3678+
3679+ std::string folder_path_;
3680+
3681+ std::string suffix_;
3682+
3683+ int64_t content_size_;
3684+
3685+ std::string download_url_;
3686+
3687+ std::string mimetype_;
3688+
3689+ std::string folder_id_;
3690+
3691+ std::unordered_map<std::string, std::string> metadata_;
3692+};
3693+
3694+CloudItem::CloudItem(const json::Value &root)
3695+ : p(std::make_shared<Priv>(root)){
3696+}
3697+
3698+const string &CloudItem::id() const {
3699+ return p->id_;
3700+}
3701+
3702+const string &CloudItem::name() const {
3703+ return p->name_;
3704+}
3705+
3706+const time_t &CloudItem::created_date() const {
3707+ return p->created_date_;
3708+}
3709+
3710+const time_t &CloudItem::updated_date() const {
3711+ return p->updated_date_;
3712+}
3713+
3714+const string &CloudItem::download_url() const {
3715+ return p->download_url_;
3716+}
3717+
3718+const string &CloudItem::folder_id() const {
3719+ return p->folder_id_;
3720+}
3721+
3722+const string &CloudItem::etag() const {
3723+ return p->etag_;
3724+}
3725+
3726+const string &CloudItem::owner() const {
3727+ return p->owner_;
3728+}
3729+
3730+CloudResource::Property CloudItem::property() const {
3731+ return CloudResource::Property::Content;
3732+}
3733+
3734+int64_t CloudItem::size() const {
3735+ return p->content_size_;
3736+}
3737+
3738+const string &CloudItem::folder_path() const
3739+{
3740+ return p->folder_path_;
3741+}
3742+
3743+const string &CloudItem::mimetype() const
3744+{
3745+ return p->mimetype_;
3746+}
3747+
3748+std::unordered_map<string, string> &CloudItem::metadata() const
3749+{
3750+ return p->metadata_;
3751+}
3752
3753=== added file 'src/onedrive/api/config.h'
3754--- src/onedrive/api/config.h 1970-01-01 00:00:00 +0000
3755+++ src/onedrive/api/config.h 2016-09-30 08:26:58 +0000
3756@@ -0,0 +1,55 @@
3757+/*
3758+ * Copyright (C) 2016 Canonical, Ltd.
3759+ *
3760+ * This library is free software; you can redistribute it and/or modify it under
3761+ * the terms of version 3 of the GNU Lesser General Public License as published
3762+ * by the Free Software Foundation.
3763+ *
3764+ * This library is distributed in the hope that it will be useful, but WITHOUT
3765+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
3766+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
3767+ * details.
3768+ *
3769+ * You should have received a copy of the GNU Lesser General Public License
3770+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3771+ *
3772+ * Author: Gary Wang <gary.wang@canonical.com>
3773+ */
3774+
3775+#ifndef ONEDRIVE_API_CONFIG_H_
3776+#define ONEDRIVE_API_CONFIG_H_
3777+
3778+#include <memory>
3779+#include <string>
3780+
3781+namespace onedrive {
3782+namespace api {
3783+
3784+struct Config {
3785+ typedef std::shared_ptr<Config> Ptr;
3786+
3787+ /*
3788+ * The access token assigned by onedrive after authenticated.
3789+ */
3790+ std::string access_token { };
3791+
3792+ /*
3793+ * The root of all API request URLs
3794+ */
3795+ std::string apiroot {"https://api.onedrive.com/v1.0"};
3796+
3797+ /*
3798+ * The custom HTTP user agent string for this library
3799+ */
3800+ std::string user_agent {"ubuntu-onedrive-lib"};
3801+
3802+ /*
3803+ * request timeout for onedrive restful api
3804+ */
3805+ int request_timeout = 1;
3806+};
3807+
3808+}
3809+}
3810+
3811+#endif /* ONEDRIVE_API_CONFIG_H_ */
3812
3813=== added file 'src/onedrive/api/downloadtask.cpp'
3814--- src/onedrive/api/downloadtask.cpp 1970-01-01 00:00:00 +0000
3815+++ src/onedrive/api/downloadtask.cpp 2016-09-30 08:26:58 +0000
3816@@ -0,0 +1,65 @@
3817+/*
3818+ * Copyright © 2016 Canonical Ltd.
3819+ *
3820+ * This program is free software: you can redistribute it and/or modify it
3821+ * under the terms of the GNU Lesser General Public License version 3,
3822+ * as published by the Free Software Foundation.
3823+ *
3824+ * This program is distributed in the hope that it will be useful,
3825+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3826+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3827+ * GNU Lesser General Public License for more details.
3828+ *
3829+ * You should have received a copy of the GNU Lesser General Public License
3830+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3831+ *
3832+ * Authored by: Gary Wang <gary.wang@canonical.com>
3833+ */
3834+
3835+#include <onedrive/api/downloadtask.h>
3836+
3837+#include "downloadtask_priv.h"
3838+#include "taskhandler.h"
3839+
3840+using namespace onedrive::api;
3841+using namespace std;
3842+
3843+DownloadTask::DownloadTask(std::shared_ptr<DownloadTaskPriv> p)
3844+ :p_(p){
3845+}
3846+
3847+const string & DownloadTask::task_url() const {
3848+ return p_->task_url();
3849+}
3850+
3851+const string &DownloadTask::error_code() const {
3852+ return p_->error_code();
3853+}
3854+
3855+Task::Status DownloadTask::status() const {
3856+ return p_->task_handler()->status();
3857+}
3858+
3859+const string & DownloadTask::content_name() const {
3860+ return p_->content_name();
3861+}
3862+
3863+const string & DownloadTask::file_path() const {
3864+ return p_->file_path();
3865+}
3866+
3867+Task::ProgressHandler & DownloadTask::progress_changed() {
3868+ return p_->progress_changed();
3869+}
3870+
3871+Task::StatusHandler & DownloadTask::status_changed() {
3872+ return p_->status_changed();
3873+}
3874+
3875+const string & DownloadTask::error_message() const {
3876+ return p_->error_string();
3877+}
3878+
3879+void DownloadTask::cancel() {
3880+ p_->task_handler()->cancel();
3881+}
3882
3883=== added file 'src/onedrive/api/downloadtask_priv.cpp'
3884--- src/onedrive/api/downloadtask_priv.cpp 1970-01-01 00:00:00 +0000
3885+++ src/onedrive/api/downloadtask_priv.cpp 2016-09-30 08:26:58 +0000
3886@@ -0,0 +1,193 @@
3887+/*
3888+ * Copyright © 2016 Canonical Ltd.
3889+ *
3890+ * This program is free software: you can redistribute it and/or modify it
3891+ * under the terms of the GNU Lesser General Public License version 3,
3892+ * as published by the Free Software Foundation.
3893+ *
3894+ * This program is distributed in the hope that it will be useful,
3895+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3896+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3897+ * GNU Lesser General Public License for more details.
3898+ *
3899+ * You should have received a copy of the GNU Lesser General Public License
3900+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3901+ *
3902+ * Authored by: Gary Wang <gary.wang@canonical.com>
3903+ */
3904+
3905+#include "downloadtask_priv.h"
3906+#include "taskhandler.h"
3907+
3908+#include <boost/filesystem.hpp>
3909+#include <json/json.h>
3910+
3911+#include <iostream>
3912+
3913+namespace json = Json;
3914+namespace fs = boost::filesystem;
3915+
3916+using namespace onedrive::api;
3917+using namespace std;
3918+
3919+namespace {
3920+static const std::string public_download_dir = std::string(getenv("HOME")) + "/Downloads";
3921+}
3922+
3923+DownloadTaskPriv::DownloadTaskPriv(const CloudItem::Ptr &root,
3924+ Task::Buffer_Callback write_cb)
3925+ :progress_handler_(nullptr),
3926+ status_handler_(nullptr),
3927+ buffer_callback_(write_cb),
3928+ task_handler_(std::make_shared<TaskHandler>())
3929+{
3930+ content_id_ = root->id();
3931+ content_name_ = root->name();
3932+ task_url_ = root->download_url();
3933+
3934+ if (!buffer_callback_) {
3935+ // create temp file path in temp path for writing
3936+ file_path_ = fs::path(fs::temp_directory_path() / fs::unique_path())
3937+ .string();
3938+ }
3939+
3940+ task_handler_->on_prepare() = [this](){
3941+ if (!buffer_callback_) {
3942+ if (ofs_.is_open())
3943+ ofs_.close();
3944+
3945+ ofs_.open(file_path_, std::ofstream::out | std::ofstream::trunc);
3946+ if (ofs_.fail()) {
3947+ throw runtime_error("failed to open file" + file_path_ + " error: " + strerror(errno));
3948+ }
3949+ }
3950+
3951+ //change status
3952+ task_handler_->set_status(Task::Status::Running);
3953+ };
3954+
3955+ task_handler_->on_progress() = [this](float percent){
3956+ if (progress_handler_) {
3957+ progress_handler_(percent);
3958+ }
3959+ };
3960+
3961+ task_handler_->on_status() = [this](Task::Status status){
3962+ if (status_handler_) {
3963+ status_handler_(status);
3964+ }
3965+ };
3966+
3967+ task_handler_->on_finished() = [this](const std::string &/*response*/) -> bool {
3968+ ofs_.close();
3969+
3970+ if (!buffer_callback_) {
3971+ std::string download_dir;
3972+ if (getenv("ONEDRIVE_DOWNLOAD_FOLDER")) {
3973+ download_dir = string(getenv("ONEDRIVE_DOWNLOAD_FOLDER"));
3974+ } else {
3975+ download_dir = public_download_dir;
3976+ }
3977+
3978+ if (!fs::exists(fs::path(download_dir))) {
3979+ try {
3980+ fs::create_directory(fs::path(download_dir));
3981+ } catch(boost::filesystem::filesystem_error& e) {
3982+ cerr << "create download directory failed"<< download_dir
3983+ << "error: " << e.what() << endl;
3984+ }
3985+ return false;
3986+ }
3987+
3988+ //check if there is a duplicate one
3989+ std::string stem = fs::path(content_name_).stem().string();
3990+ fs::path dest = download_dir + "/" + content_name_;
3991+ int dup_count = 0;
3992+ while (fs::exists(dest)) {
3993+ dest = fs::path(download_dir) / fs::path(stem
3994+ + "_"
3995+ + std::to_string(++dup_count)
3996+ + dest.extension().string());
3997+ }
3998+
3999+ try {
4000+ // rename in final when download is complete.
4001+ fs::rename(file_path_, dest);
4002+ file_path_ = dest.string();
4003+ } catch (boost::filesystem::filesystem_error& e) {
4004+ cerr << "create download directory failed"<< download_dir
4005+ << "error: " << e.what() << endl;
4006+ return false;
4007+ }
4008+ }
4009+
4010+ //change status
4011+ task_handler_->reset_broken_counter();
4012+ task_handler_->set_status(Task::Status::Complete);
4013+
4014+ return true;
4015+ };
4016+
4017+ task_handler_->on_ready_read() = [this](const string &data){
4018+ if (buffer_callback_) {
4019+ buffer_callback_((void *)data.c_str(), data.size());
4020+ } else {
4021+ ofs_.write(data.c_str(), data.size());
4022+ }
4023+ };
4024+}
4025+
4026+const string & DownloadTaskPriv::task_url() const {
4027+ return task_url_;
4028+}
4029+
4030+Task::Status DownloadTaskPriv::status() const {
4031+ return task_handler_->status();
4032+}
4033+
4034+const string & DownloadTaskPriv::content_name() const {
4035+ return content_name_;
4036+}
4037+
4038+const string & DownloadTaskPriv::file_path() const {
4039+ return file_path_;
4040+}
4041+
4042+const string &DownloadTaskPriv::error_code() const {
4043+ return error_code_;
4044+}
4045+
4046+Task::ProgressHandler & DownloadTaskPriv::progress_changed() {
4047+ return progress_handler_;
4048+}
4049+
4050+Task::StatusHandler &DownloadTaskPriv::status_changed() {
4051+ return status_handler_;
4052+}
4053+
4054+Task::Buffer_Callback &DownloadTaskPriv::buffer_callback() {
4055+ return buffer_callback_;
4056+}
4057+
4058+const string & DownloadTaskPriv::error_string() const {
4059+ return error_string_;
4060+}
4061+
4062+void DownloadTaskPriv::set_error_info(const std::string & err) {
4063+ json::Reader reader;
4064+ json::Value root;
4065+ if (reader.parse(err, root)) {
4066+ error_code_ = root["error"]["code"].asString();
4067+ error_string_ = root["error"]["message"].asString();
4068+ } else {
4069+ error_string_ = err;
4070+ }
4071+}
4072+
4073+void DownloadTaskPriv::cancel() {
4074+ task_handler_->cancel();
4075+}
4076+
4077+std::shared_ptr<TaskHandler> DownloadTaskPriv::task_handler() const {
4078+ return task_handler_;
4079+}
4080
4081=== added file 'src/onedrive/api/downloadtask_priv.h'
4082--- src/onedrive/api/downloadtask_priv.h 1970-01-01 00:00:00 +0000
4083+++ src/onedrive/api/downloadtask_priv.h 2016-09-30 08:26:58 +0000
4084@@ -0,0 +1,95 @@
4085+/*
4086+ * Copyright © 2016 Canonical Ltd.
4087+ *
4088+ * This program is free software: you can redistribute it and/or modify it
4089+ * under the terms of the GNU Lesser General Public License version 3,
4090+ * as published by the Free Software Foundation.
4091+ *
4092+ * This program is distributed in the hope that it will be useful,
4093+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4094+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4095+ * GNU Lesser General Public License for more details.
4096+ *
4097+ * You should have received a copy of the GNU Lesser General Public License
4098+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4099+ *
4100+ * Authored by: Gary Wang <gary.wang@canonical.com>
4101+ */
4102+
4103+#ifndef ONEDRIVE_API_DOWNLOADTASKPRIV_H_
4104+#define ONEDRIVE_API_DOWNLOADTASKPRIV_H_
4105+
4106+#include <onedrive/api/task.h>
4107+#include <onedrive/api/clouditem.h>
4108+
4109+#include <memory>
4110+#include <fstream>
4111+
4112+namespace onedrive {
4113+namespace api {
4114+
4115+class TaskHandler;
4116+
4117+class DownloadTaskPriv {
4118+public:
4119+ typedef std::shared_ptr<DownloadTaskPriv> Ptr;
4120+
4121+ DownloadTaskPriv(const CloudItem::Ptr &root,
4122+ Task::Buffer_Callback write_cb = nullptr);
4123+
4124+ virtual ~DownloadTaskPriv() = default;
4125+
4126+ const std::string & task_url() const;
4127+
4128+ Task::Status status() const;
4129+
4130+ const std::string & content_id() const;
4131+
4132+ const std::string & content_name() const;
4133+
4134+ const std::string & file_path() const;
4135+
4136+ const std::string & error_code() const;
4137+
4138+ const std::string & error_string() const;
4139+
4140+ void set_error_info(const std::string & err);
4141+
4142+ Task::ProgressHandler & progress_changed();
4143+
4144+ Task::StatusHandler & status_changed();
4145+
4146+ Task::Buffer_Callback & buffer_callback();
4147+
4148+ void cancel();
4149+
4150+ std::shared_ptr<TaskHandler> task_handler() const;
4151+
4152+private:
4153+ std::string content_id_;
4154+
4155+ std::string content_name_;
4156+
4157+ std::string file_path_;
4158+
4159+ std::string task_url_;
4160+
4161+ std::string error_code_;
4162+
4163+ std::string error_string_;
4164+
4165+ std::ofstream ofs_;
4166+
4167+ Task::ProgressHandler progress_handler_;
4168+
4169+ Task::StatusHandler status_handler_;
4170+
4171+ Task::Buffer_Callback buffer_callback_;
4172+
4173+ std::shared_ptr<TaskHandler> task_handler_;
4174+};
4175+
4176+}
4177+}
4178+
4179+#endif // ONEDRIVE_API_DOWNLOADTASKPRIV_H_
4180
4181=== added file 'src/onedrive/api/storageinfo.cpp'
4182--- src/onedrive/api/storageinfo.cpp 1970-01-01 00:00:00 +0000
4183+++ src/onedrive/api/storageinfo.cpp 2016-09-30 08:26:58 +0000
4184@@ -0,0 +1,64 @@
4185+/*
4186+ * Copyright © 2016 Canonical Ltd.
4187+ *
4188+ * This program is free software: you can redistribute it and/or modify it
4189+ * under the terms of the GNU Lesser General Public License version 3,
4190+ * as published by the Free Software Foundation.
4191+ *
4192+ * This program is distributed in the hope that it will be useful,
4193+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4194+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4195+ * GNU Lesser General Public License for more details.
4196+ *
4197+ * You should have received a copy of the GNU Lesser General Public License
4198+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4199+ *
4200+ * Authored by: Gary Wang <gary.wang@canonical.com>
4201+ */
4202+
4203+#include <onedrive/api/storageinfo.h>
4204+
4205+#include <json/json.h>
4206+
4207+using namespace onedrive::api;
4208+using namespace std;
4209+
4210+namespace json = Json;
4211+
4212+class StorageInfo::Priv {
4213+public:
4214+ Priv(const json::Value &root) {
4215+ id_ = root["owner"]["user"]["id"].asString();
4216+ name_ = root["owner"]["user"]["displayName"].asString();
4217+ disk_size_ = root["quota"]["total"].asUInt64();
4218+ used_disk_size_ = root["quota"]["used"].asUInt64();
4219+ }
4220+
4221+ string id_;
4222+
4223+ string name_;
4224+
4225+ int64_t used_disk_size_;
4226+
4227+ int64_t disk_size_;
4228+};
4229+
4230+StorageInfo::StorageInfo(const json::Value &root)
4231+ : p(std::make_shared<Priv>(root)){
4232+}
4233+
4234+int64_t StorageInfo::used_disk_size() const {
4235+ return p->used_disk_size_;
4236+}
4237+
4238+int64_t StorageInfo::total_disk_size() const {
4239+ return p->disk_size_;
4240+}
4241+
4242+const string & StorageInfo::id() const {
4243+ return p->id_;
4244+}
4245+
4246+const string & StorageInfo::name() const {
4247+ return p->name_;
4248+}
4249
4250=== added file 'src/onedrive/api/syncmanager.cpp'
4251--- src/onedrive/api/syncmanager.cpp 1970-01-01 00:00:00 +0000
4252+++ src/onedrive/api/syncmanager.cpp 2016-09-30 08:26:58 +0000
4253@@ -0,0 +1,70 @@
4254+/*
4255+ * Copyright © 2016 Canonical Ltd.
4256+ *
4257+ * This program is free software: you can redistribute it and/or modify it
4258+ * under the terms of the GNU Lesser General Public License version 3,
4259+ * as published by the Free Software Foundation.
4260+ *
4261+ * This program is distributed in the hope that it will be useful,
4262+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4263+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4264+ * GNU Lesser General Public License for more details.
4265+ *
4266+ * You should have received a copy of the GNU Lesser General Public License
4267+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4268+ *
4269+ * Authored by: Gary Wang <gary.wang@canonical.com>
4270+ */
4271+
4272+
4273+#include <onedrive/api/syncmanager.h>
4274+#include <onedrive/api/taskqueue.h>
4275+
4276+#include "syncthread.h"
4277+#include "client_priv.h"
4278+#include "syncmanager_priv.h"
4279+
4280+#include <iostream>
4281+
4282+using namespace onedrive::api;
4283+using namespace std;
4284+
4285+SyncManager::SyncManager(ClientPriv* client_priv)
4286+ :p_(std::make_shared<SyncManagerPriv>(client_priv)) {
4287+}
4288+
4289+void SyncManager::start() {
4290+ p_->start();
4291+}
4292+
4293+void SyncManager::cancel() {
4294+ p_->cancel();
4295+}
4296+
4297+void SyncManager::pause() {
4298+ p_->pause();
4299+}
4300+
4301+UploadTask::Ptr SyncManager::add_upload_task(const UploadRequest &request_item) {
4302+ return p_->add_upload_task(request_item);
4303+}
4304+
4305+UploadTask::Ptr SyncManager::add_upload_task(const UploadBufferCb &buffer_cb) {
4306+ return p_->add_upload_task(buffer_cb);
4307+}
4308+
4309+DownloadTask::Ptr SyncManager::add_download_task(const string &content_id) {
4310+ return p_->add_download_task(content_id);
4311+}
4312+
4313+DownloadTask::Ptr SyncManager::add_download_task(const DownloadBufferCb &buffer_cb) {
4314+ return p_->add_download_task(buffer_cb);
4315+}
4316+
4317+TaskQueue<std::shared_ptr<DownloadTask>> SyncManager::download_queue() {
4318+ return p_->download_queue();
4319+}
4320+
4321+TaskQueue<std::shared_ptr<UploadTask>> SyncManager::upload_queue() {
4322+ return p_->upload_queue();
4323+}
4324
4325=== added file 'src/onedrive/api/syncmanager_priv.cpp'
4326--- src/onedrive/api/syncmanager_priv.cpp 1970-01-01 00:00:00 +0000
4327+++ src/onedrive/api/syncmanager_priv.cpp 2016-09-30 08:26:58 +0000
4328@@ -0,0 +1,111 @@
4329+/*
4330+ * Copyright © 2016 Canonical Ltd.
4331+ *
4332+ * This program is free software: you can redistribute it and/or modify it
4333+ * under the terms of the GNU Lesser General Public License version 3,
4334+ * as published by the Free Software Foundation.
4335+ *
4336+ * This program is distributed in the hope that it will be useful,
4337+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4338+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4339+ * GNU Lesser General Public License for more details.
4340+ *
4341+ * You should have received a copy of the GNU Lesser General Public License
4342+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4343+ *
4344+ * Authored by: Gary Wang <gary.wang@canonical.com>
4345+ */
4346+
4347+#include <onedrive/api/syncmanager.h>
4348+#include <onedrive/api/taskqueue.h>
4349+
4350+#include "syncmanager_priv.h"
4351+#include "client_priv.h"
4352+#include "syncthread.h"
4353+
4354+#include <iostream>
4355+
4356+using namespace onedrive::api;
4357+using namespace std;
4358+
4359+SyncManagerPriv::SyncManagerPriv(ClientPriv *client)
4360+ : download_thread_()
4361+ , upload_thread_()
4362+ , client_(client){
4363+ start();
4364+}
4365+
4366+SyncManagerPriv::~SyncManagerPriv() {
4367+ download_thread_.stop();
4368+ upload_thread_.stop();
4369+}
4370+
4371+void SyncManagerPriv::set_access_token(const std::string &token) {
4372+ download_thread_.set_access_token(token);
4373+ upload_thread_.set_access_token(token);
4374+}
4375+
4376+DownloadTask::Ptr SyncManagerPriv::add_download_task(const string &content_id) {
4377+ auto res = client_->metadata(content_id);
4378+ auto item = std::static_pointer_cast<CloudItem>(res);
4379+ auto task_p = std::shared_ptr<DownloadTaskPriv>(new DownloadTaskPriv(item));
4380+ download_thread_.add_task(task_p);
4381+
4382+ auto task = std::shared_ptr<DownloadTask>(new DownloadTask(task_p));
4383+ download_queue_.push(task);
4384+ return task;
4385+}
4386+
4387+DownloadTask::Ptr SyncManagerPriv::add_download_task(const DownloadBufferCb &buf_item) {
4388+ auto res = client_->metadata(buf_item.content_id);
4389+ auto item = std::static_pointer_cast<CloudItem>(res);
4390+ auto task_p = std::shared_ptr<DownloadTaskPriv>(new DownloadTaskPriv(item, buf_item.write_cb));
4391+ download_thread_.add_task(task_p);
4392+
4393+ auto task = std::shared_ptr<DownloadTask>(new DownloadTask(task_p));
4394+ download_queue_.push(task);
4395+ return task;
4396+}
4397+
4398+UploadTask::Ptr SyncManagerPriv::add_upload_task(const UploadRequest &request) {
4399+ auto item_p = std::shared_ptr<UploadTaskPriv>(new UploadTaskPriv(request));
4400+ cout << "push upload link url in queue : " + item_p->task_url() << endl;
4401+ upload_thread_.add_task(item_p);
4402+
4403+ auto item = std::shared_ptr<UploadTask>(new UploadTask(item_p));
4404+ upload_queue_.push(item);
4405+ return item;
4406+}
4407+
4408+UploadTask::Ptr SyncManagerPriv::add_upload_task(const UploadBufferCb &buffer_cb) {
4409+ auto item_p = std::shared_ptr<UploadTaskPriv>(new UploadTaskPriv(buffer_cb));
4410+ cout << "push upload link url in queue : " + item_p->task_url() << endl;
4411+ upload_thread_.add_task(item_p);
4412+
4413+ auto item = std::shared_ptr<UploadTask>(new UploadTask(item_p));
4414+ upload_queue_.push(item);
4415+ return item;
4416+}
4417+
4418+TaskQueue<DownloadTask::Ptr> SyncManagerPriv::download_queue() {
4419+ return download_queue_;
4420+}
4421+
4422+TaskQueue<UploadTask::Ptr> SyncManagerPriv::upload_queue() {
4423+ return upload_queue_;
4424+}
4425+
4426+void SyncManagerPriv::start() {
4427+ download_thread_.start();
4428+ upload_thread_.start();
4429+}
4430+
4431+void SyncManagerPriv::cancel() {
4432+ download_thread_.cancel();
4433+ upload_thread_.cancel();
4434+}
4435+
4436+void SyncManagerPriv::pause() {
4437+ download_thread_.pause();
4438+ upload_thread_.pause();
4439+}
4440
4441=== added file 'src/onedrive/api/syncmanager_priv.h'
4442--- src/onedrive/api/syncmanager_priv.h 1970-01-01 00:00:00 +0000
4443+++ src/onedrive/api/syncmanager_priv.h 2016-09-30 08:26:58 +0000
4444@@ -0,0 +1,76 @@
4445+/*
4446+ * Copyright © 2016 Canonical Ltd.
4447+ *
4448+ * This program is free software: you can redistribute it and/or modify it
4449+ * under the terms of the GNU Lesser General Public License version 3,
4450+ * as published by the Free Software Foundation.
4451+ *
4452+ * This program is distributed in the hope that it will be useful,
4453+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4454+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4455+ * GNU Lesser General Public License for more details.
4456+ *
4457+ * You should have received a copy of the GNU Lesser General Public License
4458+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4459+ *
4460+ * Authored by: Gary Wang <gary.wang@canonical.com>
4461+ */
4462+
4463+#ifndef ONEDRIVE_API_SYNCMANAGERPRIV_H_
4464+#define ONEDRIVE_API_SYNCMANAGERPRIV_H_
4465+
4466+#include <onedrive/api/taskqueue.h>
4467+#include <onedrive/api/downloadtask.h>
4468+#include <onedrive/api/uploadtask.h>
4469+#include <onedrive/api/visibility.h>
4470+
4471+#include "syncthread.h"
4472+
4473+#include <memory>
4474+
4475+namespace onedrive {
4476+namespace api {
4477+
4478+class ClientPriv;
4479+
4480+class SyncManagerPriv {
4481+public:
4482+ SyncManagerPriv(ClientPriv *client);
4483+
4484+ ~SyncManagerPriv();
4485+
4486+ void set_access_token(const std::string &token);
4487+
4488+ DownloadTask::Ptr add_download_task(const std::string &content_id);
4489+
4490+ DownloadTask::Ptr add_download_task(const DownloadBufferCb &buf_item);
4491+
4492+ UploadTask::Ptr add_upload_task(const UploadRequest &request);
4493+
4494+ UploadTask::Ptr add_upload_task(const UploadBufferCb &buffer_cb);
4495+
4496+ TaskQueue<DownloadTask::Ptr> download_queue();
4497+
4498+ TaskQueue<UploadTask::Ptr> upload_queue();
4499+
4500+ void start();
4501+
4502+ void cancel();
4503+
4504+ void pause();
4505+
4506+private:
4507+ SyncThread<DownloadTaskPriv> download_thread_;
4508+ SyncThread<UploadTaskPriv> upload_thread_;
4509+
4510+ TaskQueue<DownloadTask::Ptr> download_queue_;
4511+ TaskQueue<UploadTask::Ptr> upload_queue_;
4512+
4513+ ClientPriv* client_;
4514+};
4515+
4516+
4517+}
4518+}
4519+
4520+#endif // ONEDRIVE_API_SYNCMANAGERPRIV_H_
4521
4522=== added file 'src/onedrive/api/syncthread.cpp'
4523--- src/onedrive/api/syncthread.cpp 1970-01-01 00:00:00 +0000
4524+++ src/onedrive/api/syncthread.cpp 2016-09-30 08:26:58 +0000
4525@@ -0,0 +1,447 @@
4526+/*
4527+ * Copyright © 2016 Canonical Ltd.
4528+ *
4529+ * This program is free software: you can redistribute it and/or modify it
4530+ * under the terms of the GNU Lesser General Public License version 3,
4531+ * as published by the Free Software Foundation.
4532+ *
4533+ * This program is distributed in the hope that it will be useful,
4534+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4535+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4536+ * GNU Lesser General Public License for more details.
4537+ *
4538+ * You should have received a copy of the GNU Lesser General Public License
4539+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4540+ *
4541+ * Authored by: Gary Wang <gary.wang@canonical.com>
4542+ */
4543+
4544+#include "syncthread.h"
4545+#include "taskhandler.h"
4546+#include "uploadtask_priv.h"
4547+#include "downloadtask_priv.h"
4548+
4549+#include <boost/algorithm/string.hpp>
4550+#include <core/net/http/streaming_client.h>
4551+#include <core/net/http/streaming_request.h>
4552+#include <core/net/http/response.h>
4553+#include <core/net/http/status.h>
4554+
4555+#include <fstream>
4556+#include <future>
4557+#include <iostream>
4558+
4559+namespace http = core::net::http;
4560+namespace net = core::net;
4561+
4562+using namespace onedrive::api;
4563+using namespace std;
4564+
4565+template <typename T>
4566+class SyncThread<T>::HttpStreamClient {
4567+public:
4568+ HttpStreamClient(int request_timeout) :
4569+ request_timeout_(request_timeout),
4570+ client_(http::make_streaming_client()),
4571+ worker_ { [this]() {client_->run();} }{
4572+ }
4573+
4574+ ~HttpStreamClient() {
4575+ client_->stop();
4576+ if (worker_.joinable()) {
4577+ worker_.join();
4578+ }
4579+ }
4580+
4581+ void async_get(shared_ptr<T> ptr,
4582+ const http::Header &headers) {
4583+ auto prom = make_shared<promise<bool>>();
4584+
4585+ auto task_handler = ptr->task_handler();
4586+ http::Request::Handler handler;
4587+ handler.on_progress([task_handler](const http::Request::Progress& progress)
4588+ {
4589+ if (task_handler->status() == Task::Status::Canceled) {
4590+ return http::Request::Progress::Next::abort_operation;
4591+ }
4592+
4593+ if (progress.download.current > 0.0 && progress.download.total > 0.0) {
4594+ double percent = progress.download.current / progress.download.total;
4595+ task_handler->on_progress()(percent);
4596+ }
4597+
4598+ return http::Request::Progress::Next::continue_operation;
4599+ }
4600+ );
4601+ handler.on_error([prom](const net::Error& e)
4602+ {
4603+ prom->set_exception(make_exception_ptr(runtime_error(e.what())));
4604+ });
4605+ handler.on_response([prom, task_handler](const http::Response& response)
4606+ {
4607+ if (response.status != http::Status::ok) {
4608+ prom->set_exception(make_exception_ptr(runtime_error(response.body)));
4609+ } else {
4610+ prom->set_value(task_handler->on_finished()(response.body));
4611+ }
4612+ }
4613+ );
4614+
4615+ auto http_config = http::Request::Configuration::from_uri_as_string(
4616+ ptr->task_url());
4617+ http_config.header = headers;
4618+
4619+ std::shared_future<bool> future = prom->get_future();
4620+ auto request = client_->streaming_get(http_config);
4621+ request->abort_request_if(low_speed_limit, std::chrono::seconds{low_speed_time});
4622+ request->set_timeout(std::chrono::milliseconds{request_timeout_});
4623+ request->async_execute(handler, task_handler->on_ready_read());
4624+
4625+ task_handler->attach_request(request, future);
4626+ }
4627+
4628+ void async_put(shared_ptr<T> ptr,
4629+ const http::Header &headers,
4630+ std::istream &payload,
4631+ std::size_t size) {
4632+ auto prom = make_shared<promise<bool>>();
4633+
4634+ auto task_handler = ptr->task_handler();
4635+ http::Request::Handler handler;
4636+ handler.on_progress([task_handler](const http::Request::Progress& progress)
4637+ {
4638+ if (task_handler->status() == Task::Status::Canceled) {
4639+ return http::Request::Progress::Next::abort_operation;
4640+ }
4641+
4642+ if (progress.upload.current > 0.0 && progress.upload.total > 0.0) {
4643+ double percent = (progress.upload.current / progress.upload.total);
4644+ task_handler->on_progress()(percent);
4645+ }
4646+
4647+ return http::Request::Progress::Next::continue_operation;
4648+ }
4649+ );
4650+ handler.on_error([prom](const net::Error& e)
4651+ {
4652+ prom->set_exception(make_exception_ptr(runtime_error(e.what())));
4653+ });
4654+ handler.on_response([prom, task_handler](const http::Response& response)
4655+ {
4656+ if (response.status != http::Status::ok &&
4657+ response.status != http::Status::created) {
4658+ prom->set_exception(make_exception_ptr(runtime_error(response.body)));
4659+ } else {
4660+ prom->set_value(task_handler->on_finished()(response.body));
4661+ }
4662+ }
4663+ );
4664+
4665+ auto http_config = http::Request::Configuration::from_uri_as_string(
4666+ ptr->task_url());
4667+ http_config.header = headers;
4668+
4669+ std::shared_future<bool> future = prom->get_future();
4670+ auto request = client_->streaming_put(http_config, payload, size);
4671+ request->abort_request_if(low_speed_limit, std::chrono::seconds{low_speed_time});
4672+ request->set_timeout(std::chrono::milliseconds{request_timeout_});
4673+ request->async_execute(handler, task_handler->on_ready_read());
4674+
4675+ task_handler->attach_request(request, future);
4676+ }
4677+
4678+ void async_put(shared_ptr<T> ptr,
4679+ const http::Header &headers,
4680+ std::function<size_t(void *dest, size_t buf_size)> read_cb,
4681+ std::size_t size) {
4682+ auto prom = make_shared<promise<bool>>();
4683+
4684+ auto task_handler = ptr->task_handler();
4685+ http::Request::Handler handler;
4686+ handler.on_progress([task_handler](const http::Request::Progress& progress)
4687+ {
4688+ if (task_handler->status() == Task::Status::Canceled) {
4689+ return http::Request::Progress::Next::abort_operation;
4690+ }
4691+
4692+ if (progress.upload.current > 0.0 && progress.upload.total > 0.0) {
4693+ double percent = (progress.upload.current / progress.upload.total);
4694+ task_handler->on_progress()(percent);
4695+ }
4696+
4697+ return http::Request::Progress::Next::continue_operation;
4698+ }
4699+ );
4700+ handler.on_error([prom](const net::Error& e)
4701+ {
4702+ prom->set_exception(make_exception_ptr(runtime_error(e.what())));
4703+ });
4704+ handler.on_response([prom, task_handler](const http::Response& response)
4705+ {
4706+ if (response.status != http::Status::ok &&
4707+ response.status != http::Status::created) {
4708+ prom->set_exception(make_exception_ptr(runtime_error(response.body)));
4709+ } else {
4710+ prom->set_value(task_handler->on_finished()(response.body));
4711+ }
4712+ }
4713+ );
4714+
4715+ auto http_config = http::Request::Configuration::from_uri_as_string(
4716+ ptr->task_url());
4717+ http_config.header = headers;
4718+
4719+ std::shared_future<bool> future = prom->get_future();
4720+ auto request = client_->streaming_put(http_config, read_cb, size);
4721+ request->abort_request_if(low_speed_limit, std::chrono::seconds{low_speed_time});
4722+ request->set_timeout(std::chrono::milliseconds{request_timeout_});
4723+ request->async_execute(handler, task_handler->on_ready_read());
4724+
4725+ task_handler->attach_request(request, future);
4726+ }
4727+
4728+ const int low_speed_limit = 1;
4729+
4730+ const chrono::seconds low_speed_time{chrono::seconds{10}};
4731+
4732+ int request_timeout_;
4733+
4734+ std::shared_ptr<core::net::http::StreamingClient> client_;
4735+
4736+ std::thread worker_;
4737+};
4738+
4739+template<typename T>
4740+SyncThread<T>::SyncThread()
4741+ : client_(std::make_shared<SyncThread::HttpStreamClient>(sync_timeout_ * 500)),
4742+ stop_(true){
4743+}
4744+
4745+template <typename T>
4746+SyncThread<T>::~SyncThread() {
4747+ stop();
4748+}
4749+
4750+template <typename T>
4751+void SyncThread<T>::start() {
4752+ pause_ = false;
4753+
4754+ if (stop_ == true) {
4755+ stop_ = false;
4756+ thread_ = std::thread(&SyncThread::run, this);
4757+ } else {
4758+ //if it's running, then resume
4759+ for (auto & item_ptr : task_queue_) {
4760+ if (item_ptr->status() == Task::Status::Paused) {
4761+ item_ptr->task_handler()->resume();
4762+ }
4763+ }
4764+ }
4765+}
4766+
4767+template <typename T>
4768+void SyncThread<T>::cancel() {
4769+ stop();
4770+}
4771+
4772+template <typename T>
4773+void SyncThread<T>::pause() {
4774+ std::unique_lock<std::mutex> lock(mutex_);
4775+
4776+ //pause task if it's running
4777+ for (auto & item_ptr : task_queue_) {
4778+ if (item_ptr->status() == Task::Status::Running) {
4779+ item_ptr->task_handler()->pause();
4780+ }
4781+ }
4782+
4783+ pause_ = true;
4784+}
4785+
4786+template <typename T>
4787+void SyncThread<T>::stop() {
4788+ //cancel task if it's running or prepared in the queue.
4789+ for (auto & item_ptr : task_queue_) {
4790+ if (item_ptr->status() == Task::Status::Running
4791+ || item_ptr->status() == Task::Status::Paused
4792+ || item_ptr->status() == Task::Status::Unstart) {
4793+ item_ptr->task_handler()->cancel();
4794+ }
4795+ }
4796+
4797+ {
4798+ std::unique_lock<std::mutex> lock(mutex_);
4799+ if (stop_)
4800+ return;
4801+
4802+ //terminate thread
4803+ stop_ = true;
4804+ con_.notify_all();
4805+ }
4806+
4807+ if (thread_.joinable())
4808+ thread_.join();
4809+}
4810+
4811+template <typename T>
4812+void SyncThread<T>::set_access_token(const std::string &token) {
4813+ access_token_ = token;
4814+}
4815+
4816+template <typename T>
4817+void SyncThread<T>::add_task(std::shared_ptr<T> task_ptr) {
4818+ task_queue_.push(task_ptr);
4819+}
4820+
4821+template <typename T>
4822+void SyncThread<T>::run() {
4823+ std::unique_lock<std::mutex> lock(mutex_);
4824+
4825+ std::future_status status = std::future_status::ready;
4826+ std::shared_ptr<DownloadTaskPriv> task_ptr = nullptr;
4827+
4828+ while(!stop_) {
4829+ con_.wait_for(lock, std::chrono::seconds(sync_timeout_));
4830+ if (!stop_ && !pause_) {
4831+ if (status == std::future_status::ready) {
4832+ //check if there is unstared task item in task queue
4833+ typename TaskQueue<std::shared_ptr<T>>::const_iterator it = std::find_if(
4834+ task_queue_.begin(),
4835+ task_queue_.end(),
4836+ [](std::shared_ptr<T> task){
4837+ return (task->status() == Task::Status::Unstart);
4838+ });
4839+
4840+ if (it == task_queue_.end())
4841+ continue;
4842+
4843+ http::Header header;
4844+ header.add("Authorization", "bearer " + access_token_);
4845+ task_ptr = (*it);
4846+ try {
4847+ task_ptr->task_handler()->on_prepare()();
4848+ } catch (std::runtime_error e) {
4849+ cerr << "error: " << e.what() << endl;
4850+ continue;
4851+ }
4852+ client_->async_get(task_ptr, header);
4853+ }
4854+
4855+ if (task_ptr) {
4856+ auto task_handler = task_ptr->task_handler();
4857+ //do not wait block here forever until download is finished,
4858+ //that gives a chance to pause/resume download from sync thread.
4859+ status = task_handler->wait_for(std::chrono::seconds(sync_timeout_));
4860+ try {
4861+ if (status == std::future_status::ready &&
4862+ task_handler->get_result()) {
4863+ cout << "download content successfully:" <<
4864+ task_ptr->file_path() << endl;
4865+ task_handler->detach_request();
4866+ task_ptr.reset();
4867+ }
4868+ } catch(std::runtime_error &e) {
4869+ // if error is caused by net issue,not manually(application callback)
4870+ // increase broken counter and try it again. Once broken counter exceeds broken limit,
4871+ // it's regarded as the "broken" one and drop it
4872+ if (task_handler->status() != Task::Status::Canceled) {
4873+ if (!task_handler->is_broken()) {
4874+ task_handler->add_broken_counter();
4875+ task_handler->set_status(Task::Status::Unstart);
4876+ } else {
4877+ task_ptr->set_error_info(e.what());
4878+ task_handler->set_status(Task::Status::Broken);
4879+ }
4880+ }
4881+
4882+ cerr << "download content: "<< task_ptr->content_name()
4883+ << " error: " << e.what() << endl;
4884+ task_ptr.reset();
4885+ }
4886+ }
4887+ }
4888+ }
4889+}
4890+
4891+namespace onedrive {
4892+namespace api {
4893+
4894+template <>
4895+void SyncThread<UploadTaskPriv>::run() {
4896+ std::unique_lock<std::mutex> lock(mutex_);
4897+
4898+ std::future_status status = std::future_status::ready;
4899+ UploadTaskPriv::Ptr task_ptr = nullptr;
4900+ while(!stop_) {
4901+ con_.wait_for(lock, std::chrono::seconds(sync_timeout_));
4902+
4903+ if (!stop_ && !pause_) {
4904+ if (status == std::future_status::ready) {
4905+ //check if there is unstared task item in task queue
4906+ typename TaskQueue<UploadTaskPriv::Ptr>::const_iterator it = std::find_if(
4907+ task_queue_.begin(),
4908+ task_queue_.end(),
4909+ [](UploadTaskPriv::Ptr task){
4910+ return (task->status() == Task::Status::Unstart);
4911+ });
4912+
4913+ if (it == task_queue_.end())
4914+ continue;
4915+
4916+ http::Header header;
4917+ header.add("Authorization", "bearer " + access_token_);
4918+ task_ptr = (*it);
4919+ task_ptr->task_handler()->on_prepare()();
4920+ if (task_ptr->buffer_callback()) {
4921+ client_->async_put(task_ptr, header, task_ptr->buffer_callback(), task_ptr->file_size());
4922+ } else {
4923+ client_->async_put(task_ptr, header, task_ptr->ifstream(), task_ptr->file_size());
4924+ }
4925+ }
4926+
4927+ if (task_ptr) {
4928+ auto task_handler = task_ptr->task_handler();
4929+ //do not wait block here forever until upload is finished,
4930+ //that gives a chance to pause/resume upload from sync thread.
4931+ status = task_handler->wait_for(std::chrono::seconds(sync_timeout_));
4932+ try {
4933+ if (status == std::future_status::ready &&
4934+ task_handler->get_result()) {
4935+ cout << "upload content successfully:" << task_ptr->content_name() << endl;
4936+ task_handler->detach_request();
4937+ task_ptr.reset();
4938+ }
4939+ }catch (std::runtime_error &e) {
4940+ //if content data is fetched chunk by chunk(buffering), set it broken once failed
4941+ //as we didn't cache buffer locally.
4942+ if (task_ptr->buffer_callback()) {
4943+ task_ptr->set_error_info(e.what());
4944+ task_handler->set_status(Task::Status::Broken);
4945+ } else if (task_handler->status() != Task::Status::Canceled) {
4946+ // if content data is local file, when error is caused by net issue,
4947+ //increase broken counter and try it again. Once broken counter exceeds broken limit,
4948+ //it's regarded as the "broken" one and we drop it.
4949+
4950+ if (!task_handler->is_broken()) {
4951+ task_handler->add_broken_counter();
4952+ task_handler->set_status(Task::Status::Unstart);
4953+ } else {
4954+ task_ptr->set_error_info(e.what());
4955+ task_handler->set_status(Task::Status::Broken);
4956+ }
4957+ }
4958+
4959+ cerr << "upload content: "<< task_ptr->content_name()
4960+ << " error: " << e.what() << endl;
4961+ task_ptr.reset();
4962+ }
4963+ }
4964+ }
4965+ }
4966+}
4967+
4968+}
4969+}
4970+
4971+template class SyncThread<DownloadTaskPriv>;
4972+template class SyncThread<UploadTaskPriv>;
4973
4974=== added file 'src/onedrive/api/syncthread.h'
4975--- src/onedrive/api/syncthread.h 1970-01-01 00:00:00 +0000
4976+++ src/onedrive/api/syncthread.h 2016-09-30 08:26:58 +0000
4977@@ -0,0 +1,81 @@
4978+/*
4979+ * Copyright (C) 2016 Canonical, Ltd.
4980+ *
4981+ * This library is free software; you can redistribute it and/or modify it under
4982+ * the terms of version 3 of the GNU Lesser General Public License as published
4983+ * by the Free Software Foundation.
4984+ *
4985+ * This library is distributed in the hope that it will be useful, but WITHOUT
4986+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
4987+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
4988+ * details.
4989+ *
4990+ * You should have received a copy of the GNU Lesser General Public License
4991+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
4992+ *
4993+ * Author: Gary Wang <gary.wang@canonical.com>
4994+ */
4995+
4996+#ifndef ONEDRIVE_API_SYNCTHREAD_H_
4997+#define ONEDRIVE_API_SYNCTHREAD_H_
4998+
4999+#include <onedrive/api/taskqueue.h>
5000+#include <onedrive/api/visibility.h>
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: