PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/gnome-online-accounts-3.5.4/src/goabackend/goawindowsliveprovider.c

#
C | 434 lines | 321 code | 64 blank | 49 comment | 33 complexity | 99192197331078a72889a2e4f519f93b MD5 | raw file
Possible License(s): LGPL-2.0
  1. /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
  2. /*
  3. * Copyright (C) 2011 Red Hat, Inc.
  4. * Copyright (C) 2011 Collabora Ltd.
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General
  17. * Public License along with this library; if not, write to the
  18. * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  19. * Boston, MA 02111-1307, USA.
  20. *
  21. * Authors: David Zeuthen <davidz@redhat.com>
  22. * Xavier Claessens <xclaesse@gmail.com>
  23. */
  24. #include "config.h"
  25. #include <glib/gi18n-lib.h>
  26. #include <rest/rest-proxy.h>
  27. #include <json-glib/json-glib.h>
  28. #include <libsoup/soup-gnome.h>
  29. #include <webkit/webkit.h>
  30. #include "goaprovider.h"
  31. #include "goaoauth2provider.h"
  32. #include "goawindowsliveprovider.h"
  33. /**
  34. * GoaWindowsLiveProvider:
  35. *
  36. * The #GoaWindowsLiveProvider structure contains only private data and should
  37. * only be accessed using the provided API.
  38. */
  39. struct _GoaWindowsLiveProvider
  40. {
  41. /*< private >*/
  42. GoaOAuth2Provider parent_instance;
  43. };
  44. typedef struct _GoaWindowsLiveProviderClass GoaWindowsLiveProviderClass;
  45. struct _GoaWindowsLiveProviderClass
  46. {
  47. GoaOAuth2ProviderClass parent_class;
  48. };
  49. /**
  50. * SECTION:goawindowsliveprovider
  51. * @title: GoaWindowsLiveProvider
  52. * @short_description: A provider for Windows Live accounts
  53. *
  54. * #GoaWindowsLiveProvider is used for handling Windows Live accounts.
  55. */
  56. G_DEFINE_TYPE_WITH_CODE (GoaWindowsLiveProvider, goa_windows_live_provider, GOA_TYPE_OAUTH2_PROVIDER,
  57. g_io_extension_point_implement (GOA_PROVIDER_EXTENSION_POINT_NAME,
  58. g_define_type_id,
  59. "windows_live",
  60. 0));
  61. /* ---------------------------------------------------------------------------------------------------- */
  62. static const gchar *
  63. get_provider_type (GoaProvider *_provider)
  64. {
  65. return "windows_live";
  66. }
  67. static gchar *
  68. get_provider_name (GoaProvider *_provider,
  69. GoaObject *object)
  70. {
  71. return g_strdup (_("Windows Live"));
  72. }
  73. static GIcon *
  74. get_provider_icon (GoaProvider *provider,
  75. GoaObject *object)
  76. {
  77. return g_themed_icon_new_with_default_fallbacks ("goa-account-msn");
  78. }
  79. static const gchar *
  80. get_authorization_uri (GoaOAuth2Provider *provider)
  81. {
  82. return "https://oauth.live.com/authorize";
  83. }
  84. static const gchar *
  85. get_token_uri (GoaOAuth2Provider *provider)
  86. {
  87. return "https://oauth.live.com/token";
  88. }
  89. static const gchar *
  90. get_redirect_uri (GoaOAuth2Provider *provider)
  91. {
  92. return "https://oauth.live.com/desktop";
  93. }
  94. static const gchar *
  95. get_scope (GoaOAuth2Provider *provider)
  96. {
  97. return "wl.messenger,"
  98. "wl.offline_access,"
  99. "wl.skydrive_update,"
  100. "wl.emails";
  101. }
  102. static guint
  103. get_credentials_generation (GoaProvider *provider)
  104. {
  105. return 1;
  106. }
  107. static const gchar *
  108. get_client_id (GoaOAuth2Provider *provider)
  109. {
  110. return GOA_WINDOWS_LIVE_CLIENT_ID;
  111. }
  112. static const gchar *
  113. get_client_secret (GoaOAuth2Provider *provider)
  114. {
  115. return NULL;
  116. }
  117. static const gchar *
  118. get_authentication_cookie (GoaOAuth2Provider *provider)
  119. {
  120. return "MSNPPAuth";
  121. }
  122. /* ---------------------------------------------------------------------------------------------------- */
  123. static gchar *
  124. get_identity_sync (GoaOAuth2Provider *provider,
  125. const gchar *access_token,
  126. gchar **out_presentation_identity,
  127. GCancellable *cancellable,
  128. GError **error)
  129. {
  130. RestProxy *proxy;
  131. RestProxyCall *call;
  132. JsonParser *parser;
  133. JsonObject *json_object;
  134. gchar *ret;
  135. gchar *id;
  136. gchar *presentation_identity;
  137. ret = NULL;
  138. proxy = NULL;
  139. call = NULL;
  140. parser = NULL;
  141. id = NULL;
  142. presentation_identity = NULL;
  143. /* TODO: cancellable */
  144. proxy = rest_proxy_new ("https://apis.live.net/v5.0/me", FALSE);
  145. call = rest_proxy_new_call (proxy);
  146. rest_proxy_call_set_method (call, "GET");
  147. rest_proxy_call_add_param (call, "access_token", access_token);
  148. if (!rest_proxy_call_sync (call, error))
  149. goto out;
  150. if (rest_proxy_call_get_status_code (call) != 200)
  151. {
  152. g_set_error (error,
  153. GOA_ERROR,
  154. GOA_ERROR_FAILED,
  155. _("Expected status 200 when requesting guid, instead got status %d (%s)"),
  156. rest_proxy_call_get_status_code (call),
  157. rest_proxy_call_get_status_message (call));
  158. goto out;
  159. }
  160. parser = json_parser_new ();
  161. if (!json_parser_load_from_data (parser,
  162. rest_proxy_call_get_payload (call),
  163. rest_proxy_call_get_payload_length (call),
  164. error))
  165. {
  166. g_prefix_error (error, _("Error parsing response as JSON: "));
  167. goto out;
  168. }
  169. json_object = json_node_get_object (json_parser_get_root (parser));
  170. id = g_strdup (json_object_get_string_member (json_object, "id"));
  171. if (id == NULL)
  172. {
  173. g_set_error (error,
  174. GOA_ERROR,
  175. GOA_ERROR_FAILED,
  176. _("Didn't find id member in JSON data"));
  177. goto out;
  178. }
  179. json_object = json_object_get_object_member (json_object, "emails");
  180. presentation_identity = g_strdup (json_object_get_string_member (json_object, "account"));
  181. if (presentation_identity == NULL)
  182. {
  183. g_set_error (error,
  184. GOA_ERROR,
  185. GOA_ERROR_FAILED,
  186. _("Didn't find account email member in JSON data"));
  187. goto out;
  188. }
  189. ret = id;
  190. id = NULL;
  191. if (out_presentation_identity != NULL)
  192. {
  193. *out_presentation_identity = presentation_identity;
  194. presentation_identity = NULL;
  195. }
  196. out:
  197. g_free (id);
  198. g_free (presentation_identity);
  199. if (call != NULL)
  200. g_object_unref (call);
  201. if (proxy != NULL)
  202. g_object_unref (proxy);
  203. return ret;
  204. }
  205. /* ---------------------------------------------------------------------------------------------------- */
  206. static gboolean
  207. is_deny_node (GoaOAuth2Provider *provider, WebKitDOMNode *node)
  208. {
  209. WebKitDOMHTMLInputElement *input_element;
  210. gboolean ret;
  211. gchar *name;
  212. name = NULL;
  213. ret = FALSE;
  214. if (!WEBKIT_DOM_IS_HTML_INPUT_ELEMENT (node))
  215. goto out;
  216. input_element = WEBKIT_DOM_HTML_INPUT_ELEMENT (node);
  217. name = webkit_dom_html_input_element_get_name (input_element);
  218. if (g_strcmp0 (name, "submitNo") != 0)
  219. goto out;
  220. ret = TRUE;
  221. out:
  222. g_free (name);
  223. return ret;
  224. }
  225. /* ---------------------------------------------------------------------------------------------------- */
  226. static gboolean
  227. build_object (GoaProvider *provider,
  228. GoaObjectSkeleton *object,
  229. GKeyFile *key_file,
  230. const gchar *group,
  231. gboolean just_added,
  232. GError **error)
  233. {
  234. GoaAccount *account;
  235. GoaChat *chat = NULL;
  236. GoaDocuments *documents;
  237. gboolean chat_enabled;
  238. gboolean documents_enabled;
  239. gboolean ret = FALSE;
  240. account = NULL;
  241. /* Chain up */
  242. if (!GOA_PROVIDER_CLASS (goa_windows_live_provider_parent_class)->build_object (provider,
  243. object,
  244. key_file,
  245. group,
  246. just_added,
  247. error))
  248. goto out;
  249. account = goa_object_get_account (GOA_OBJECT (object));
  250. /* Chat */
  251. chat = goa_object_get_chat (GOA_OBJECT (object));
  252. chat_enabled = g_key_file_get_boolean (key_file, group, "ChatEnabled", NULL);
  253. if (chat_enabled)
  254. {
  255. if (chat == NULL)
  256. {
  257. chat = goa_chat_skeleton_new ();
  258. goa_object_skeleton_set_chat (object, chat);
  259. }
  260. }
  261. else
  262. {
  263. if (chat != NULL)
  264. goa_object_skeleton_set_chat (object, NULL);
  265. }
  266. /* Documents */
  267. documents = goa_object_get_documents (GOA_OBJECT (object));
  268. documents_enabled = g_key_file_get_boolean (key_file, group, "DocumentsEnabled", NULL);
  269. if (documents_enabled)
  270. {
  271. if (documents == NULL)
  272. {
  273. documents = goa_documents_skeleton_new ();
  274. goa_object_skeleton_set_documents (object, documents);
  275. }
  276. }
  277. else
  278. {
  279. if (documents != NULL)
  280. goa_object_skeleton_set_documents (object, NULL);
  281. }
  282. if (just_added)
  283. {
  284. goa_account_set_chat_disabled (account, !chat_enabled);
  285. goa_account_set_documents_disabled (account, !documents_enabled);
  286. g_signal_connect (account,
  287. "notify::chat-disabled",
  288. G_CALLBACK (goa_util_account_notify_property_cb),
  289. "ChatEnabled");
  290. g_signal_connect (account,
  291. "notify::documents-disabled",
  292. G_CALLBACK (goa_util_account_notify_property_cb),
  293. "DocumentsEnabled");
  294. }
  295. ret = TRUE;
  296. out:
  297. if (chat != NULL)
  298. g_object_unref (chat);
  299. if (account != NULL)
  300. g_object_unref (account);
  301. return ret;
  302. }
  303. static gboolean
  304. get_use_external_browser (GoaOAuth2Provider *provider)
  305. {
  306. return FALSE;
  307. }
  308. /* ---------------------------------------------------------------------------------------------------- */
  309. static void
  310. show_account (GoaProvider *provider,
  311. GoaClient *client,
  312. GoaObject *object,
  313. GtkBox *vbox,
  314. GtkGrid *left,
  315. GtkGrid *right)
  316. {
  317. /* Chain up */
  318. GOA_PROVIDER_CLASS (goa_windows_live_provider_parent_class)->show_account (provider,
  319. client,
  320. object,
  321. vbox,
  322. left,
  323. right);
  324. goa_util_add_row_switch_from_keyfile_with_blurb (left, right, object,
  325. _("Use for"),
  326. "chat-disabled",
  327. _("Chat"));
  328. goa_util_add_row_switch_from_keyfile_with_blurb (left, right, object,
  329. NULL,
  330. "documents-disabled",
  331. _("Documents"));
  332. }
  333. /* ---------------------------------------------------------------------------------------------------- */
  334. static void
  335. add_account_key_values (GoaOAuth2Provider *provider,
  336. GVariantBuilder *builder)
  337. {
  338. g_variant_builder_add (builder, "{ss}", "ChatEnabled", "true");
  339. g_variant_builder_add (builder, "{ss}", "DocumentsEnabled", "true");
  340. }
  341. /* ---------------------------------------------------------------------------------------------------- */
  342. static void
  343. goa_windows_live_provider_init (GoaWindowsLiveProvider *client)
  344. {
  345. }
  346. static void
  347. goa_windows_live_provider_class_init (GoaWindowsLiveProviderClass *klass)
  348. {
  349. GoaProviderClass *provider_class;
  350. GoaOAuth2ProviderClass *oauth2_class;
  351. provider_class = GOA_PROVIDER_CLASS (klass);
  352. provider_class->get_provider_type = get_provider_type;
  353. provider_class->get_provider_name = get_provider_name;
  354. provider_class->get_provider_icon = get_provider_icon;
  355. provider_class->build_object = build_object;
  356. provider_class->show_account = show_account;
  357. provider_class->get_credentials_generation = get_credentials_generation;
  358. oauth2_class = GOA_OAUTH2_PROVIDER_CLASS (klass);
  359. oauth2_class->get_authorization_uri = get_authorization_uri;
  360. oauth2_class->get_token_uri = get_token_uri;
  361. oauth2_class->get_redirect_uri = get_redirect_uri;
  362. oauth2_class->get_scope = get_scope;
  363. oauth2_class->get_client_id = get_client_id;
  364. oauth2_class->get_client_secret = get_client_secret;
  365. oauth2_class->get_authentication_cookie = get_authentication_cookie;
  366. oauth2_class->get_identity_sync = get_identity_sync;
  367. oauth2_class->is_deny_node = is_deny_node;
  368. oauth2_class->get_use_external_browser = get_use_external_browser;
  369. oauth2_class->add_account_key_values = add_account_key_values;
  370. }