Merge lp:~gary-wzl77/account-plugins/mcloud-plugin-lp1587282 into lp:account-plugins
- mcloud-plugin-lp1587282
- Merge into trunk
Proposed by
Gary.Wang
Status: | Superseded |
---|---|
Proposed branch: | lp:~gary-wzl77/account-plugins/mcloud-plugin-lp1587282 |
Merge into: | lp:account-plugins |
Diff against target: |
1037 lines (+874/-2) 19 files modified
.bzrignore (+3/-0) Makefile.am (+12/-0) configure.ac (+25/-0) data/providers/mcloud.provider.in.in (+29/-0) data/providers/owncloud.provider.in.in (+13/-0) data/providers/vk.provider.in.in (+26/-0) debian/account-plugin-mcloud.install (+4/-0) debian/account-plugin-owncloud.install (+3/-0) debian/account-plugin-vk.install (+3/-0) debian/control (+23/-0) debian/rules (+4/-1) qml/Makefile.am (+4/-1) qml/mcloud/ErrorItem.qml (+48/-0) qml/mcloud/Main.qml (+7/-0) qml/mcloud/OAuth.qml (+283/-0) qml/mcloud/WebView.qml (+94/-0) qml/owncloud/Main.qml (+27/-0) qml/owncloud/NewAccount.qml (+230/-0) qml/vk/Main.qml (+36/-0) |
To merge this branch: | bzr merge lp:~gary-wzl77/account-plugins/mcloud-plugin-lp1587282 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Online Accounts | Pending | ||
Review via email: mp+296087@code.launchpad.net |
This proposal has been superseded by a proposal from 2016-05-31.
Commit message
Add mcloud plugin.
Description of the change
Add mcloud plugin
Testing instructions:
1) manually install the account-
2) download and install mcloud scope package from
https:/
3) launch mcloud scope and click "Login to MCloud"
To post a comment you must log in.
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2016-04-05 10:03:39 +0000 |
3 | +++ .bzrignore 2016-05-31 09:01:17 +0000 |
4 | @@ -28,10 +28,13 @@ |
5 | /debian/account-plugin-google/ |
6 | /debian/account-plugin-icons/ |
7 | /debian/account-plugin-identica/ |
8 | +/debian/account-plugin-mcloud/ |
9 | +/debian/account-plugin-owncloud/ |
10 | /debian/account-plugin-sina/ |
11 | /debian/account-plugin-sohu/ |
12 | /debian/account-plugin-tools/ |
13 | /debian/account-plugin-twitter/ |
14 | +/debian/account-plugin-vk/ |
15 | /debian/account-plugin-windows-live/ |
16 | /debian/autoreconf.after |
17 | /debian/autoreconf.before |
18 | |
19 | === modified file 'Makefile.am' |
20 | --- Makefile.am 2016-04-05 10:46:13 +0000 |
21 | +++ Makefile.am 2016-05-31 09:01:17 +0000 |
22 | @@ -89,9 +89,12 @@ |
23 | data/providers/identica.provider.in.in \ |
24 | data/providers/linkedin.provider.in.in \ |
25 | data/providers/instagram.provider.in.in \ |
26 | + data/providers/mcloud.provider.in.in \ |
27 | + data/providers/owncloud.provider.in.in \ |
28 | data/providers/sina.provider.in.in \ |
29 | data/providers/sohu.provider.in.in \ |
30 | data/providers/twitter.provider.in.in \ |
31 | + data/providers/vk.provider.in.in \ |
32 | data/providers/windows-live.provider.in.in |
33 | |
34 | providers_DATA = \ |
35 | @@ -132,6 +135,15 @@ |
36 | data/webkit-options/login.live.com.conf \ |
37 | data/webkit-options/www.linkedin.com.conf |
38 | |
39 | +# Temporary until these bugs are fixed: |
40 | +# https://bugs.launchpad.net/bugs/1567908 |
41 | +# https://bugs.launchpad.net/bugs/1571587 |
42 | +iconsdir = $(datadir)/icons/hicolor/32x32/apps |
43 | +dist_icons_DATA = \ |
44 | + data/icons/mcloud.png \ |
45 | + data/icons/owncloud.png \ |
46 | + data/icons/vk.png |
47 | + |
48 | dist_bin_SCRIPTS = \ |
49 | tools/account-console |
50 | |
51 | |
52 | === modified file 'configure.ac' |
53 | --- configure.ac 2016-04-05 10:03:39 +0000 |
54 | +++ configure.ac 2016-05-31 09:01:17 +0000 |
55 | @@ -228,6 +228,28 @@ |
56 | AC_SUBST(SOHU_CLIENT_ID, ["$sohu_client_id"]) |
57 | AC_SUBST(SOHU_CLIENT_SECRET, ["$sohu_client_secret"]) |
58 | |
59 | +# Set Mcloud client id/secret |
60 | +AC_ARG_WITH(mcloud-client-id, |
61 | + [AS_HELP_STRING([--with-mcloud-client-id], |
62 | + [Mcloud client id])], |
63 | + [mcloud_client_id=$withval], |
64 | + [mcloud_client_id="APP1ZtqoN3R0002"]) |
65 | +AC_ARG_WITH(mcloud-client-secret, |
66 | + [AS_HELP_STRING([--with-mcloud-client-secret], |
67 | + [Mcloud client secret])], |
68 | + [mcloud_client_secret=$withval], |
69 | + [mcloud_client_secret="A70EFCDC91456349E7FDECF0A33574AC"]) |
70 | +AC_SUBST(MCLOUD_CLIENT_ID, ["$mcloud_client_id"]) |
71 | +AC_SUBST(MCLOUD_CLIENT_SECRET, ["$mcloud_client_secret"]) |
72 | + |
73 | +# Set VK client id |
74 | +AC_ARG_WITH(vk-client-id, |
75 | + [AS_HELP_STRING([--with-vk-client-id], |
76 | + [VK client ID])], |
77 | + [vk_client_id=$withval], |
78 | + [vk_client_id="5404010"]) |
79 | +AC_SUBST(VK_CLIENT_ID, ["$vk_client_id"]) |
80 | + |
81 | # Set Windows Live client id |
82 | AC_ARG_WITH(windows-live-client-id, |
83 | [AS_HELP_STRING([--with-windows-live-client-id], |
84 | @@ -244,9 +266,12 @@ |
85 | data/providers/identica.provider.in |
86 | data/providers/linkedin.provider.in |
87 | data/providers/instagram.provider.in |
88 | + data/providers/mcloud.provider.in |
89 | + data/providers/owncloud.provider.in |
90 | data/providers/sina.provider.in |
91 | data/providers/sohu.provider.in |
92 | data/providers/twitter.provider.in |
93 | + data/providers/vk.provider.in |
94 | data/providers/windows-live.provider.in |
95 | Makefile |
96 | po/Makefile.in |
97 | |
98 | === added directory 'data/icons' |
99 | === added file 'data/icons/mcloud.png' |
100 | Binary files data/icons/mcloud.png 1970-01-01 00:00:00 +0000 and data/icons/mcloud.png 2016-05-31 09:01:17 +0000 differ |
101 | === added file 'data/icons/owncloud.png' |
102 | Binary files data/icons/owncloud.png 1970-01-01 00:00:00 +0000 and data/icons/owncloud.png 2016-05-31 09:01:17 +0000 differ |
103 | === added file 'data/icons/vk.png' |
104 | Binary files data/icons/vk.png 1970-01-01 00:00:00 +0000 and data/icons/vk.png 2016-05-31 09:01:17 +0000 differ |
105 | === added file 'data/providers/mcloud.provider.in.in' |
106 | --- data/providers/mcloud.provider.in.in 1970-01-01 00:00:00 +0000 |
107 | +++ data/providers/mcloud.provider.in.in 2016-05-31 09:01:17 +0000 |
108 | @@ -0,0 +1,29 @@ |
109 | +<?xml version="1.0" encoding="UTF-8"?> |
110 | +<provider id="mcloud"> |
111 | + <name>MCloud</name> |
112 | + <icon>mcloud</icon> |
113 | + <translations>MCloud</translations> |
114 | + <domains>.*10086\.cn</domains> |
115 | + <plugin>generic-oauth</plugin> |
116 | + <single-account>true</single-account> |
117 | + <template> |
118 | + <group name="auth"> |
119 | + <setting name="method">oauth2</setting> |
120 | + <setting name="mechanism">user_agent</setting> |
121 | + <group name="oauth2"> |
122 | + <group name="user_agent"> |
123 | + <setting name="Host">caiyun.feixin.10086.cn</setting> |
124 | + <setting name="AuthPath">authorize.jsp</setting> |
125 | + <setting name="TokenPath">access_token</setting> |
126 | + <setting name="RedirectUri">http://developer.ubuntu.com/en/</setting> |
127 | + <setting name="ResponseType">code</setting> |
128 | + <setting name="ClientId">@MCLOUD_CLIENT_ID@</setting> |
129 | + <setting type="as" name="Scope">['nd_cloud']</setting> |
130 | + <setting name="ForceClientAuthViaRequestBody" type="b">true</setting> |
131 | + <setting name="DisableStateParameter" type="b">true</setting> |
132 | + <setting type="as" name="AllowedSchemes">['https', 'http']</setting> |
133 | + </group> |
134 | + </group> |
135 | + </group> |
136 | + </template> |
137 | +</provider> |
138 | |
139 | === added file 'data/providers/owncloud.provider.in.in' |
140 | --- data/providers/owncloud.provider.in.in 1970-01-01 00:00:00 +0000 |
141 | +++ data/providers/owncloud.provider.in.in 2016-05-31 09:01:17 +0000 |
142 | @@ -0,0 +1,13 @@ |
143 | +<?xml version="1.0" encoding="UTF-8"?> |
144 | +<provider id="owncloud"> |
145 | + <name>ownCloud</name> |
146 | + <icon>owncloud.png</icon> |
147 | + <translations>account-plugins</translations> |
148 | + |
149 | + <template> |
150 | + <group name="auth"> |
151 | + <setting name="method">password</setting> |
152 | + <setting name="mechanism">password</setting> |
153 | + </group> |
154 | + </template> |
155 | +</provider> |
156 | |
157 | === added file 'data/providers/vk.provider.in.in' |
158 | --- data/providers/vk.provider.in.in 1970-01-01 00:00:00 +0000 |
159 | +++ data/providers/vk.provider.in.in 2016-05-31 09:01:17 +0000 |
160 | @@ -0,0 +1,26 @@ |
161 | +<?xml version="1.0" encoding="UTF-8"?> |
162 | +<provider id="vk"> |
163 | + <name>VKontakte</name> |
164 | + <icon>vk</icon> |
165 | + <translations>account-plugins</translations> |
166 | + <domains>.*vk\.com</domains> |
167 | + |
168 | + <template> |
169 | + <group name="auth"> |
170 | + <setting name="method">oauth2</setting> |
171 | + <setting name="mechanism">user_agent</setting> |
172 | + <group name="oauth2"> |
173 | + <group name="user_agent"> |
174 | + <setting name="Host">oauth.vk.com</setting> |
175 | + <setting name="AuthPath">authorize</setting> |
176 | + <setting name="TokenPath">access_token</setting> |
177 | + <setting name="RedirectUri">https://oauth.vk.com/blank.html</setting> |
178 | + <setting name="ResponseType">token</setting> |
179 | + <setting name="ClientId">@VK_CLIENT_ID@</setting> |
180 | + <setting type="as" name="Scope">['offline']</setting> |
181 | + <setting type="s" name="v">5.50</setting> |
182 | + </group> |
183 | + </group> |
184 | + </group> |
185 | + </template> |
186 | +</provider> |
187 | |
188 | === added file 'debian/account-plugin-mcloud.install' |
189 | --- debian/account-plugin-mcloud.install 1970-01-01 00:00:00 +0000 |
190 | +++ debian/account-plugin-mcloud.install 2016-05-31 09:01:17 +0000 |
191 | @@ -0,0 +1,4 @@ |
192 | +usr/share/accounts/providers/mcloud.provider |
193 | +usr/share/accounts/qml-plugins/mcloud/*.qml |
194 | +usr/share/icons/hicolor/32x32/apps/mcloud.png |
195 | + |
196 | |
197 | === added file 'debian/account-plugin-owncloud.install' |
198 | --- debian/account-plugin-owncloud.install 1970-01-01 00:00:00 +0000 |
199 | +++ debian/account-plugin-owncloud.install 2016-05-31 09:01:17 +0000 |
200 | @@ -0,0 +1,3 @@ |
201 | +usr/share/accounts/providers/owncloud.provider |
202 | +usr/share/accounts/qml-plugins/owncloud/*.qml |
203 | +usr/share/icons/hicolor/32x32/apps/owncloud.png |
204 | |
205 | === added file 'debian/account-plugin-vk.install' |
206 | --- debian/account-plugin-vk.install 1970-01-01 00:00:00 +0000 |
207 | +++ debian/account-plugin-vk.install 2016-05-31 09:01:17 +0000 |
208 | @@ -0,0 +1,3 @@ |
209 | +usr/share/accounts/providers/vk.provider |
210 | +usr/share/accounts/qml-plugins/vk/Main.qml |
211 | +usr/share/icons/hicolor/32x32/apps/vk.png |
212 | |
213 | === modified file 'debian/control' |
214 | --- debian/control 2016-04-05 10:52:46 +0000 |
215 | +++ debian/control 2016-05-31 09:01:17 +0000 |
216 | @@ -144,6 +144,29 @@ |
217 | Description: GNOME Control Center account plugin for single signon - Instagram |
218 | GNOME Control Center account plugins for single signon |
219 | |
220 | +Package: account-plugin-mcloud |
221 | +Architecture: all |
222 | +Depends: ${misc:Depends}, |
223 | + ubuntu-system-settings-online-accounts, |
224 | +Description: Account plugin for online accounts - mCloud |
225 | + Online Accounts plugin provide the user interface to create accounts for |
226 | + third party services. |
227 | + |
228 | +Package: account-plugin-owncloud |
229 | +Architecture: all |
230 | +Depends: ${misc:Depends}, |
231 | + ubuntu-system-settings-online-accounts, |
232 | +Description: Account plugin for online accounts - ownCloud |
233 | + Online Accounts plugin provide the user interface to create accounts for |
234 | + third party services. |
235 | + |
236 | +Package: account-plugin-vk |
237 | +Architecture: all |
238 | +Depends: ${misc:Depends}, |
239 | + libaccount-plugin-generic-oauth | ubuntu-system-settings-online-accounts, |
240 | +Description: GNOME Control Center account plugin for single signon - VKontakte |
241 | + GNOME Control Center account plugins for single signon |
242 | + |
243 | Package: account-plugin-tools |
244 | Architecture: all |
245 | Depends: ${misc:Depends}, |
246 | |
247 | === modified file 'debian/rules' |
248 | --- debian/rules 2015-07-23 14:10:26 +0000 |
249 | +++ debian/rules 2016-05-31 09:01:17 +0000 |
250 | @@ -21,7 +21,10 @@ |
251 | --with-linkedin-consumer-key="34gnzrg96iq5" \ |
252 | --with-linkedin-consumer-secret="BazRki2LE8eZtcqh" \ |
253 | --with-instagram-client-id="01c3df41a2274a14882adea8e8ebbd46" \ |
254 | - --with-instagram-client-secret="4751ccdc39c648719ea83cfb1c866c26" |
255 | + --with-instagram-client-secret="4751ccdc39c648719ea83cfb1c866c26" \ |
256 | + --with-mcloud-client-id="APP1ZtqoN3R0002" \ |
257 | + --with-mcloud-client-secret="A70EFCDC91456349E7FDECF0A33574AC" \ |
258 | + --with-vk-client-id="5402699" |
259 | |
260 | override_dh_install: |
261 | rm -f debian/*/usr/lib/*/*/*.la |
262 | |
263 | === modified file 'qml/Makefile.am' |
264 | --- qml/Makefile.am 2013-06-07 11:56:25 +0000 |
265 | +++ qml/Makefile.am 2016-05-31 09:01:17 +0000 |
266 | @@ -2,4 +2,7 @@ |
267 | facebook/Main.qml \ |
268 | flickr/Main.qml \ |
269 | google/Main.qml \ |
270 | - twitter/Main.qml |
271 | + owncloud/Main.qml \ |
272 | + owncloud/NewAccount.qml \ |
273 | + twitter/Main.qml \ |
274 | + vk/Main.qml |
275 | |
276 | === added directory 'qml/mcloud' |
277 | === added file 'qml/mcloud/ErrorItem.qml' |
278 | --- qml/mcloud/ErrorItem.qml 1970-01-01 00:00:00 +0000 |
279 | +++ qml/mcloud/ErrorItem.qml 2016-05-31 09:01:17 +0000 |
280 | @@ -0,0 +1,48 @@ |
281 | +/* |
282 | + * Copyright (C) 2015 Canonical Ltd. |
283 | + * |
284 | + * Contact: Alberto Mardegan <alberto.mardegan@canonical.com> |
285 | + * |
286 | + * This program is free software: you can redistribute it and/or modify it |
287 | + * under the terms of the GNU General Public License version 3, as published |
288 | + * by the Free Software Foundation. |
289 | + * |
290 | + * This program is distributed in the hope that it will be useful, but |
291 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
292 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
293 | + * PURPOSE. See the GNU General Public License for more details. |
294 | + * |
295 | + * You should have received a copy of the GNU General Public License along |
296 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
297 | + */ |
298 | + |
299 | +import QtQuick 2.0 |
300 | +import Ubuntu.Components 0.1 |
301 | +import Ubuntu.Components.ListItems 0.1 as ListItem |
302 | + |
303 | +Item { |
304 | + id: root |
305 | + |
306 | + signal retryRequested() |
307 | + |
308 | + Column { |
309 | + anchors { |
310 | + verticalCenter: parent.verticalCenter |
311 | + left: parent.left; right: parent.right |
312 | + } |
313 | + spacing: units.gu(2) |
314 | + |
315 | + Label { |
316 | + anchors { left: parent.left; right: parent.right } |
317 | + text: i18n.dtr("ubuntu-system-settings-online-accounts", "This service is not available right now. Try again later.") |
318 | + wrapMode: Text.WordWrap |
319 | + horizontalAlignment: Text.AlignHCenter |
320 | + } |
321 | + |
322 | + Button { |
323 | + anchors.horizontalCenter: parent.horizontalCenter |
324 | + text: i18n.dtr("ubuntu-system-settings-online-accounts", "Try Again") |
325 | + onClicked: root.retryRequested() |
326 | + } |
327 | + } |
328 | +} |
329 | |
330 | === added file 'qml/mcloud/Main.qml' |
331 | --- qml/mcloud/Main.qml 1970-01-01 00:00:00 +0000 |
332 | +++ qml/mcloud/Main.qml 2016-05-31 09:01:17 +0000 |
333 | @@ -0,0 +1,7 @@ |
334 | +import Ubuntu.OnlineAccounts.Plugin 1.0 |
335 | +import "." as Local |
336 | + |
337 | +OAuthMain { |
338 | + creationComponent: Local.OAuth { |
339 | + } |
340 | +} |
341 | |
342 | === added file 'qml/mcloud/OAuth.qml' |
343 | --- qml/mcloud/OAuth.qml 1970-01-01 00:00:00 +0000 |
344 | +++ qml/mcloud/OAuth.qml 2016-05-31 09:01:17 +0000 |
345 | @@ -0,0 +1,283 @@ |
346 | +/* |
347 | + * Copyright (C) 2013-2016 Canonical Ltd. |
348 | + * |
349 | + * Contact: Alberto Mardegan <alberto.mardegan@canonical.com> |
350 | + * |
351 | + * This program is free software: you can redistribute it and/or modify it |
352 | + * under the terms of the GNU General Public License version 3, as published |
353 | + * by the Free Software Foundation. |
354 | + * |
355 | + * This program is distributed in the hope that it will be useful, but |
356 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
357 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
358 | + * PURPOSE. See the GNU General Public License for more details. |
359 | + * |
360 | + * You should have received a copy of the GNU General Public License along |
361 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
362 | + */ |
363 | + |
364 | +import QtQuick 2.0 |
365 | +import Ubuntu.Components 1.3 |
366 | +import Ubuntu.Components.ListItems 1.3 as ListItem |
367 | +import Ubuntu.Components.Popups 1.3 |
368 | +import Ubuntu.OnlineAccounts 0.1 |
369 | +import Ubuntu.OnlineAccounts.Plugin 1.0 |
370 | + |
371 | +Item { |
372 | + id: root |
373 | + |
374 | + /* To override the parameters coming from the .provider file: */ |
375 | + property variant authenticationParameters: {} |
376 | + /* To override the default access control list: */ |
377 | + property variant accessControlList: ["unconfined"] |
378 | + |
379 | + property variant authReply |
380 | + property bool isNewAccount: false |
381 | + property variant __account: account |
382 | + property bool __isAuthenticating: false |
383 | + property alias globalAccountService: globalAccountSettings |
384 | + property bool loading: loader.status == Loader.Null || loader.status == Loader.Loading |
385 | + |
386 | + signal authenticated(variant reply) |
387 | + signal authenticationError(variant error) |
388 | + signal finished |
389 | + |
390 | + anchors.fill: parent |
391 | + |
392 | + Component.onCompleted: { |
393 | + isNewAccount = (account.accountId === 0) |
394 | + enableAccount() |
395 | + authenticate() |
396 | + } |
397 | + |
398 | + RequestHandler { |
399 | + id: requestHandler |
400 | + onRequestChanged: { |
401 | + if (request) { |
402 | + console.log("RequestHandler captured request!") |
403 | + loader.setSource("WebView.qml", { |
404 | + "signonRequest": request |
405 | + }) |
406 | + } else { |
407 | + console.log("Request destroyed!") |
408 | + loader.source = "" |
409 | + } |
410 | + } |
411 | + } |
412 | + |
413 | + Credentials { |
414 | + id: creds |
415 | + caption: account.provider.id |
416 | + acl: accessControlList |
417 | + onCredentialsIdChanged: root.credentialsStored() |
418 | + } |
419 | + |
420 | + AccountService { |
421 | + id: globalAccountSettings |
422 | + objectHandle: account.accountServiceHandle |
423 | + credentials: creds |
424 | + autoSync: false |
425 | + |
426 | + onAuthenticated: { |
427 | + __isAuthenticating = false |
428 | + authReply = reply |
429 | + root.authenticated(reply) |
430 | + } |
431 | + onAuthenticationError: { |
432 | + __isAuthenticating = false |
433 | + root.authenticationError(error) |
434 | + } |
435 | + } |
436 | + |
437 | + AccountServiceModel { |
438 | + id: accountServices |
439 | + includeDisabled: true |
440 | + account: __account.objectHandle |
441 | + } |
442 | + |
443 | + ListItem.Base { |
444 | + visible: loading && !errorItem.visible |
445 | + height: units.gu(7) |
446 | + showDivider: false |
447 | + anchors.top: parent.top |
448 | + |
449 | + Item { |
450 | + height: units.gu(5) |
451 | + width: units.gu(30) |
452 | + anchors.horizontalCenter: parent.horizontalCenter |
453 | + anchors.top: parent.top |
454 | + anchors.margins: units.gu(1) |
455 | + |
456 | + ActivityIndicator { |
457 | + id: loadingIndicator |
458 | + anchors.verticalCenter: parent.verticalCenter |
459 | + anchors.left: parent.left |
460 | + anchors.leftMargin: units.gu(5) |
461 | + running: loading |
462 | + z: 1 |
463 | + } |
464 | + Label { |
465 | + text: i18n.dtr("ubuntu-system-settings-online-accounts", "Loading…") |
466 | + anchors.verticalCenter: parent.verticalCenter |
467 | + anchors.left: loadingIndicator.right |
468 | + anchors.leftMargin: units.gu(3) |
469 | + } |
470 | + } |
471 | + } |
472 | + |
473 | + Loader { |
474 | + id: loader |
475 | + anchors { |
476 | + top: parent.top |
477 | + left: parent.left |
478 | + right: parent.right |
479 | + bottom: Qt.inputMethod.visible ? osk.top : cancelButton.top |
480 | + } |
481 | + focus: true |
482 | + visible: !loading |
483 | + } |
484 | + |
485 | + ErrorItem { |
486 | + id: errorItem |
487 | + anchors { fill: parent; margins: units.gu(4) } |
488 | + visible: false |
489 | + onRetryRequested: { |
490 | + root.credentialsStored() |
491 | + visible = false |
492 | + } |
493 | + } |
494 | + |
495 | + KeyboardRectangle { |
496 | + id: osk |
497 | + } |
498 | + |
499 | + ListItem.SingleControl { |
500 | + id: cancelButton |
501 | + anchors.bottom: parent.bottom |
502 | + showDivider: false |
503 | + control: Button { |
504 | + text: i18n.dtr("ubuntu-system-settings-online-accounts", "Cancel") |
505 | + width: parent.width - units.gu(4) |
506 | + onClicked: root.cancel() |
507 | + } |
508 | + } |
509 | + |
510 | + AccountServiceModel { |
511 | + id: possiblyDuplicateAccounts |
512 | + service: "global" |
513 | + provider: __account.provider.id |
514 | + } |
515 | + |
516 | + function authenticate() { |
517 | + console.log("Authenticating...") |
518 | + creds.sync() |
519 | + } |
520 | + |
521 | + function credentialsStored() { |
522 | + console.log("Credentials stored, id: " + creds.credentialsId) |
523 | + if (creds.credentialsId == 0) return |
524 | + var parameters = {} |
525 | + parameters[requestHandler.matchKey] = requestHandler.matchId |
526 | + parameters["providerId"] = account.provider.id |
527 | + for (var p in authenticationParameters) { |
528 | + parameters[p] = authenticationParameters[p] |
529 | + } |
530 | + __isAuthenticating = true |
531 | + globalAccountSettings.authenticate(parameters) |
532 | + } |
533 | + |
534 | + function cancel() { |
535 | + if (__isAuthenticating) { |
536 | + /* This will cause the authentication to fail, and this method will |
537 | + * be invoked again to delete the credentials. */ |
538 | + globalAccountSettings.cancelAuthentication() |
539 | + return |
540 | + } |
541 | + if (isNewAccount && creds.credentialsId != 0) { |
542 | + console.log("Removing credentials...") |
543 | + creds.remove() |
544 | + creds.removed.connect(finished) |
545 | + } else { |
546 | + finished() |
547 | + } |
548 | + } |
549 | + |
550 | + function enableAccount() { |
551 | + globalAccountSettings.updateServiceEnabled(true) |
552 | + } |
553 | + |
554 | + function getUserName(reply, callback) { |
555 | + /* This should work for OAuth 1.0a; for OAuth 2.0 this function needs |
556 | + * to be reimplemented */ |
557 | + if ('ScreenName' in reply) return reply.ScreenName |
558 | + else if ('UserId' in reply) return reply.UserId |
559 | + return '' |
560 | + } |
561 | + |
562 | + function accountIsDuplicate(userName) { |
563 | + var model = possiblyDuplicateAccounts |
564 | + for (var i = 0; i < model.count; i++) { |
565 | + if (model.get(i, "displayName") == userName) |
566 | + return true |
567 | + } |
568 | + return false |
569 | + } |
570 | + |
571 | + function __gotUserName(userName, reply) { |
572 | + console.log("UserName: " + userName) |
573 | + if (userName != '') { |
574 | + if (accountIsDuplicate(userName)) { |
575 | + var dialog = PopupUtils.open(Qt.resolvedUrl("DuplicateAccount.qml")) |
576 | + dialog.closed.connect(cancel) |
577 | + return |
578 | + } |
579 | + account.updateDisplayName(userName) |
580 | + } |
581 | + beforeSaving(reply) |
582 | + } |
583 | + |
584 | + function saveAccount() { |
585 | + account.synced.connect(finished) |
586 | + account.sync() |
587 | + } |
588 | + |
589 | + /* reimplement this function in plugins in order to perform some actions |
590 | + * before quitting the plugin */ |
591 | + function beforeSaving(reply) { |
592 | + saveAccount() |
593 | + } |
594 | + |
595 | + function __getUserNameAndSave(reply) { |
596 | + /* If the completeCreation function is defined, run it */ |
597 | + if (typeof(completeCreation) == "function") { |
598 | + console.warn("The completeCreation method is deprecated; use getUserName() or beforeSaving() instead") |
599 | + completeCreation(reply) |
600 | + return |
601 | + } |
602 | + |
603 | + var userName = getUserName(reply, function(name) { |
604 | + __gotUserName(name, reply) |
605 | + }) |
606 | + if (typeof(userName) == "string") { |
607 | + __gotUserName(userName, reply) |
608 | + } else if (userName === false) { |
609 | + cancel() |
610 | + return |
611 | + } |
612 | + // otherwise (userName === true), wait for the callback to be invoked |
613 | + } |
614 | + |
615 | + onAuthenticated: __getUserNameAndSave(reply) |
616 | + |
617 | + onAuthenticationError: { |
618 | + console.log("Authentication error, code " + error.code) |
619 | + if (error.code == AccountService.NetworkError) { |
620 | + console.log("Network error") |
621 | + errorItem.visible = true |
622 | + return |
623 | + } |
624 | + root.cancel() |
625 | + } |
626 | + |
627 | + onFinished: loading = false |
628 | +} |
629 | |
630 | === added file 'qml/mcloud/WebView.qml' |
631 | --- qml/mcloud/WebView.qml 1970-01-01 00:00:00 +0000 |
632 | +++ qml/mcloud/WebView.qml 2016-05-31 09:01:17 +0000 |
633 | @@ -0,0 +1,94 @@ |
634 | +import QtQuick 2.0 |
635 | +import Ubuntu.Components 1.1 |
636 | +import Ubuntu.Web 0.2 |
637 | + |
638 | +WebView { |
639 | + id: root |
640 | + |
641 | + property QtObject signonRequest |
642 | + readonly property string token_url: "https://ose.caiyun.feixin.10086.cn/oauthApp/OAuth2/getToken" |
643 | + readonly property string redirect_url: "http://developer.ubuntu.com/en/" |
644 | + readonly property string client_id: "APP1ZtqoN3R0002" |
645 | + readonly property string client_pass: "A70EFCDC91456349E7FDECF0A33574AC" |
646 | + |
647 | + Component.onCompleted: { |
648 | + signonRequest.authenticated.connect(onAuthenticated) |
649 | + url = signonRequest.startUrl |
650 | + } |
651 | + |
652 | + //1.WORKAROUND: we need to retrieve refresh token instead of access token. |
653 | + function fetchRefreshToken(code) { |
654 | + var http = new XMLHttpRequest() |
655 | + var body = "grant_type=authorization_code&code="+code+"&redirect_uri="+redirect_url |
656 | + |
657 | + http.open("POST", token_url, true); |
658 | + http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); |
659 | + http.setRequestHeader("Authorization", "Basic " + Qt.btoa(client_id + ":" + client_pass)); |
660 | + http.onreadystatechange = function() { |
661 | + if (http.readyState === 4 && http.status == 200) { |
662 | + var response = JSON.parse(http.responseText) |
663 | + //create a fake access_token with refresh token. |
664 | + var urlStr = redirect_url+"#access_token="+response.refresh_token |
665 | + var authUrl = Qt.resolvedUrl(urlStr); |
666 | + signonRequest.currentUrl = authUrl |
667 | + } else { |
668 | + console.log("error: " + http.status) |
669 | + } |
670 | + }; |
671 | + |
672 | + http.send(body); |
673 | + } |
674 | + |
675 | + onLoadingStateChanged: { |
676 | + if (loading) { |
677 | + signonRequest.onLoadStarted() |
678 | + } else if (lastLoadSucceeded) { |
679 | + signonRequest.onLoadFinished(true) |
680 | + } else { |
681 | + signonRequest.onLoadFinished(false) |
682 | + } |
683 | + } |
684 | + |
685 | + onUrlChanged: { |
686 | + //2.WORKAROUND: retrieve refresh token if code is fetched |
687 | + var code_pattern= new RegExp("\\?code=.*&"); |
688 | + var urlStr = url.toString() |
689 | + if (code_pattern.test(urlStr)){ |
690 | + var code = urlStr.match(/\?code=(.*)&/)[1]; |
691 | + console.log("code::", code) |
692 | + fetchRefreshToken(code) |
693 | + } else { |
694 | + signonRequest.currentUrl = url |
695 | + } |
696 | + } |
697 | + |
698 | + //3.WORKAROUND: Apply desktop useragent to prevent server from detecting android client, |
699 | + //which causes authentication failure. |
700 | + context: WebContext { |
701 | + dataPath: signonRequest ? signonRequest.rootDir : "" |
702 | + userAgent: "Mozilla/5.0 (Linux; Ubuntu 14.04) AppleWebKit/537.36 Chromium/35.0.1870.2 Safari/537.36" |
703 | + } |
704 | + |
705 | + function onAuthenticated() { |
706 | + /* Get the cookies and set them on the request */ |
707 | + console.log("Authenticated; getting cookies") |
708 | + context.cookieManager.getCookiesResponse.connect(onGotCookies) |
709 | + context.cookieManager.getAllCookies() |
710 | + visible = false |
711 | + } |
712 | + |
713 | + function onGotCookies(requestId, cookies) { |
714 | + signonRequest.setCookies(cookies) |
715 | + } |
716 | + |
717 | + /* Taken from webbrowser-app */ |
718 | + ProgressBar { |
719 | + anchors.top: parent.top |
720 | + anchors.left: parent.left |
721 | + anchors.right: parent.right |
722 | + height: units.dp(3) |
723 | + showProgressPercentage: false |
724 | + visible: root.loading |
725 | + value: root.loadProgress / 100 |
726 | + } |
727 | +} |
728 | |
729 | === added directory 'qml/owncloud' |
730 | === added file 'qml/owncloud/Main.qml' |
731 | --- qml/owncloud/Main.qml 1970-01-01 00:00:00 +0000 |
732 | +++ qml/owncloud/Main.qml 2016-05-31 09:01:17 +0000 |
733 | @@ -0,0 +1,27 @@ |
734 | +import QtQuick 2.0 |
735 | +import Ubuntu.OnlineAccounts.Plugin 1.0 |
736 | + |
737 | +Flickable { |
738 | + id: root |
739 | + |
740 | + property int keyboardSize: Qt.inputMethod.visible ? Qt.inputMethod.keyboardRectangle.height : 0 |
741 | + contentHeight: loader.item.height + keyboardSize |
742 | + |
743 | + signal finished |
744 | + |
745 | + Loader { |
746 | + id: loader |
747 | + anchors.fill: parent |
748 | + sourceComponent: newAccountComponent |
749 | + |
750 | + Connections { |
751 | + target: loader.item |
752 | + onFinished: root.finished() |
753 | + } |
754 | + } |
755 | + |
756 | + Component { |
757 | + id: newAccountComponent |
758 | + NewAccount {} |
759 | + } |
760 | +} |
761 | |
762 | === added file 'qml/owncloud/NewAccount.qml' |
763 | --- qml/owncloud/NewAccount.qml 1970-01-01 00:00:00 +0000 |
764 | +++ qml/owncloud/NewAccount.qml 2016-05-31 09:01:17 +0000 |
765 | @@ -0,0 +1,230 @@ |
766 | +import QtQuick 2.0 |
767 | +import Ubuntu.Components 1.3 |
768 | +import Ubuntu.OnlineAccounts 0.1 |
769 | + |
770 | +Item { |
771 | + id: root |
772 | + |
773 | + signal finished |
774 | + |
775 | + anchors.margins: units.gu(1) |
776 | + height: contents.height |
777 | + |
778 | + property var __account: account |
779 | + property string __host: "" |
780 | + property bool __busy: false |
781 | + property string __hostError: i18n.dtr("account-plugins", "Invalid host URL") |
782 | + |
783 | + Column { |
784 | + id: contents |
785 | + anchors { left: parent.left; right: parent.right } |
786 | + spacing: units.gu(1) |
787 | + |
788 | + Label { |
789 | + id: errorLabel |
790 | + anchors { left: parent.left; right: parent.right } |
791 | + font.bold: true |
792 | + color: UbuntuColors.red |
793 | + wrapMode: Text.Wrap |
794 | + visible: !__busy && text != "" |
795 | + } |
796 | + |
797 | + Label { |
798 | + anchors { left: parent.left; right: parent.right } |
799 | + text: i18n.dtr("account-plugins", "URL:") |
800 | + } |
801 | + |
802 | + TextField { |
803 | + id: urlField |
804 | + anchors { left: parent.left; right: parent.right } |
805 | + placeholderText: i18n.dtr("account-plugins", "http://example.org") |
806 | + focus: true |
807 | + enabled: !__busy |
808 | + |
809 | + inputMethodHints: Qt.ImhUrlCharactersOnly |
810 | + } |
811 | + |
812 | + Label { |
813 | + anchors { left: parent.left; right: parent.right } |
814 | + text: i18n.dtr("account-plugins", "Username:") |
815 | + } |
816 | + |
817 | + TextField { |
818 | + id: usernameField |
819 | + anchors { left: parent.left; right: parent.right } |
820 | + placeholderText: i18n.dtr("account-plugins", "Your username") |
821 | + enabled: !__busy |
822 | + inputMethodHints: Qt.ImhNoAutoUppercase + Qt.ImhNoPredictiveText + Qt.ImhPreferLowercase |
823 | + |
824 | + KeyNavigation.tab: passwordField |
825 | + } |
826 | + |
827 | + Label { |
828 | + anchors { left: parent.left; right: parent.right } |
829 | + text: i18n.dtr("account-plugins", "Password:") |
830 | + } |
831 | + |
832 | + TextField { |
833 | + id: passwordField |
834 | + anchors { left: parent.left; right: parent.right } |
835 | + placeholderText: i18n.dtr("account-plugins", "Your password") |
836 | + echoMode: TextInput.Password |
837 | + enabled: !__busy |
838 | + |
839 | + inputMethodHints: Qt.ImhSensitiveData |
840 | + Keys.onReturnPressed: login() |
841 | + } |
842 | + |
843 | + Row { |
844 | + id: buttons |
845 | + anchors { left: parent.left; right: parent.right } |
846 | + height: units.gu(5) |
847 | + spacing: units.gu(1) |
848 | + Button { |
849 | + id: btnCancel |
850 | + text: i18n.dtr("account-plugins", "Cancel") |
851 | + height: parent.height |
852 | + width: (parent.width / 2) - 0.5 * parent.spacing |
853 | + onClicked: finished() |
854 | + } |
855 | + Button { |
856 | + id: btnContinue |
857 | + text: i18n.dtr("account-plugins", "Continue") |
858 | + color: UbuntuColors.green |
859 | + height: parent.height |
860 | + width: (parent.width / 2) - 0.5 * parent.spacing |
861 | + onClicked: login() |
862 | + enabled: !__busy |
863 | + } |
864 | + } |
865 | + } |
866 | + |
867 | + ActivityIndicator { |
868 | + anchors.centerIn: parent |
869 | + running: __busy |
870 | + } |
871 | + |
872 | + Credentials { |
873 | + id: creds |
874 | + caption: account.provider.id |
875 | + acl: [ "unconfined" ] |
876 | + storeSecret: true |
877 | + onCredentialsIdChanged: root.credentialsStored() |
878 | + } |
879 | + |
880 | + AccountService { |
881 | + id: globalAccountSettings |
882 | + objectHandle: account.accountServiceHandle |
883 | + autoSync: false |
884 | + } |
885 | + |
886 | + function login() { |
887 | + __host = cleanUrl(urlField.text) |
888 | + var username = usernameField.text |
889 | + var password = passwordField.text |
890 | + |
891 | + errorLabel.text = "" |
892 | + __busy = true |
893 | + var host = __host |
894 | + var tryHttp = false |
895 | + if (__host.indexOf("http") != 0) { |
896 | + host = "https://" + __host |
897 | + tryHttp = true |
898 | + } |
899 | + |
900 | + checkAccount(host, username, password, function cb(success) { |
901 | + console.log("callback called: " + success) |
902 | + if (success) { |
903 | + saveData(host, username, password) |
904 | + } else if (tryHttp) { |
905 | + host = "http://" + __host |
906 | + tryHttp = false |
907 | + checkAccount(host, username, password, cb) |
908 | + } else { |
909 | + __busy = false |
910 | + } |
911 | + }) |
912 | + } |
913 | + |
914 | + function saveData(host, username, password) { |
915 | + __host = host |
916 | + var strippedHost = __host.replace(/^https?:\/\//, '') |
917 | + account.updateDisplayName(username + '@' + strippedHost) |
918 | + creds.userName = username |
919 | + creds.secret = password |
920 | + creds.sync() |
921 | + } |
922 | + |
923 | + function findChild(node, tagName) { |
924 | + if (!node) return node; |
925 | + var children = node.childNodes |
926 | + for (var i = 0; i < children.length; i++) { |
927 | + if (children[i].nodeName == tagName) { |
928 | + return children[i] |
929 | + } |
930 | + } |
931 | + return null |
932 | + } |
933 | + |
934 | + function checkAccount(host, username, password, callback) { |
935 | + console.log("Trying host " + host + " as " + username + ':' + password) |
936 | + var request = new XMLHttpRequest(); |
937 | + request.onreadystatechange = function() { |
938 | + if (request.readyState === XMLHttpRequest.DONE) { |
939 | + console.log("response: " + request.responseText) |
940 | + if (request.status == 200) { |
941 | + var root = request.responseXML ? request.responseXML.documentElement : null |
942 | + var metaElement = findChild(root, "meta") |
943 | + var statusElement = findChild(metaElement, "status") |
944 | + if (statusElement && statusElement.childNodes.length > 0 && |
945 | + statusElement.childNodes[0].nodeValue == "ok") { |
946 | + callback(true) |
947 | + } else { |
948 | + var statusCodeElement = findChild(metaElement, "statuscode") |
949 | + var statusCode = (statusCodeElement && statusCodeElement.childNodes.length > 0) ? |
950 | + statusCodeElement.childNodes[0].nodeValue : "999" |
951 | + if (statusCode == "999") { |
952 | + showError(__hostError) |
953 | + } else { |
954 | + showError(i18n.dtr("account-plugins", "Invalid username or password")) |
955 | + } |
956 | + callback(false) |
957 | + } |
958 | + } else { |
959 | + showError(__hostError) |
960 | + callback(false) |
961 | + } |
962 | + } |
963 | + } |
964 | + request.open("POST", host + "/ocs/v1.php/person/check", true); |
965 | + request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); |
966 | + var body = "login=" + username + "&password=" + password |
967 | + request.send(body); |
968 | + } |
969 | + |
970 | + function showError(message) { |
971 | + if (!errorLabel.text) errorLabel.text = message |
972 | + } |
973 | + |
974 | + function credentialsStored() { |
975 | + console.log("Credentials stored, id: " + creds.credentialsId) |
976 | + if (creds.credentialsId == 0) return |
977 | + |
978 | + globalAccountSettings.updateServiceEnabled(true) |
979 | + globalAccountSettings.credentials = creds |
980 | + globalAccountSettings.updateSettings({ |
981 | + "host": __host |
982 | + }) |
983 | + account.synced.connect(finished) |
984 | + account.sync() |
985 | + __busy = false |
986 | + } |
987 | + |
988 | + // check host url for http |
989 | + function cleanUrl(url) { |
990 | + var host = url.trim() |
991 | + // if the user typed trailing '/' or "index.php", strip that |
992 | + return host.replace(/\/(index.php)?\/*$/, '') |
993 | + } |
994 | + |
995 | +} |
996 | |
997 | === added directory 'qml/vk' |
998 | === added file 'qml/vk/Main.qml' |
999 | --- qml/vk/Main.qml 1970-01-01 00:00:00 +0000 |
1000 | +++ qml/vk/Main.qml 2016-05-31 09:01:17 +0000 |
1001 | @@ -0,0 +1,36 @@ |
1002 | +import Ubuntu.OnlineAccounts.Plugin 1.0 |
1003 | + |
1004 | +OAuthMain { |
1005 | + creationComponent: OAuth { |
1006 | + function completeCreation(reply) { |
1007 | + console.log("Access token: " + reply.AccessToken) |
1008 | + var http = new XMLHttpRequest() |
1009 | + var url = "https://api.vk.com/method/users.get?access_token=" + reply.AccessToken + "&fields=nickname,first_name,last_name"; |
1010 | + http.open("GET", url, true); |
1011 | + http.onreadystatechange = function() { |
1012 | + if (http.readyState === 4){ |
1013 | + if (http.status == 200) { |
1014 | + console.log("ok") |
1015 | + console.log("response text: " + http.responseText) |
1016 | + var response = JSON.parse(http.responseText) |
1017 | + if (response.response && response.response.length > 0) { |
1018 | + var data = response.response[0] |
1019 | + var name = data.first_name + " " + data.last_name |
1020 | + if (data.nickname) { |
1021 | + name += " (" + data.nickname + ")" |
1022 | + } |
1023 | + account.updateDisplayName(name) |
1024 | + } |
1025 | + account.synced.connect(finished) |
1026 | + account.sync() |
1027 | + } else { |
1028 | + console.log("error: " + http.status) |
1029 | + cancel() |
1030 | + } |
1031 | + } |
1032 | + }; |
1033 | + |
1034 | + http.send(null); |
1035 | + } |
1036 | + } |
1037 | +} |