Commit dd279e87 authored by Bastien Nocera's avatar Bastien Nocera
Browse files

Remove Pocket and deprecate org.gnome.OnlineAccounts.ReadLater

The non-standard OAuth is causing maintenance problem and the maintainer
has already disabled Pocket in certain distributions, as there aren't
any core GNOME applications using it as part of the core experience.

Remove the code so that applications don't try and use this
implementation with no future.
parent b8a6f2a8
......@@ -60,17 +60,6 @@ We are allowed to embed the client_secret in the source code. See
https://developers.google.com/accounts/docs/OAuth2InstalledApp#overview
Pocket
------
OAuth 2.0 variant:
https://getpocket.com/developer/docs/authentication
Authenticating with a Firefox Account is not documented. These slides are
useful:
http://www.slideshare.net/KuoE0/pocket-authentication-with-oauth-on-firefox-os
Windows Live
------------
......
......@@ -303,24 +303,6 @@ if test "$enable_windows_live" != "no"; then
AC_DEFINE(GOA_WINDOWS_LIVE_ENABLED, 1, [Enable Windows Live data provider])
fi
# Pocket
AC_DEFINE(GOA_POCKET_NAME, ["pocket"], [ProviderType and extension point name])
AC_ARG_ENABLE([pocket],
[AS_HELP_STRING([--enable-pocket], [Enable Pocket provider])],
[],
[enable_pocket=yes])
AC_ARG_WITH(pocket-client-id,
[AS_HELP_STRING([--with-pocket-client-id], [Pocket OAuth 2.0 client id])],
[],
[])
if test "$with_pocket_client_id" = ""; then
with_pocket_client_id="16630-40b25246b56e8ad5310b2883"
fi
AC_DEFINE_UNQUOTED(GOA_POCKET_CLIENT_ID, ["$with_pocket_client_id"], [Pocket OAuth 2.0 client id])
if test "$enable_pocket" != "no"; then
AC_DEFINE(GOA_POCKET_ENABLED, 1, [Enable Pocket data provider])
fi
# Kerberos
AC_DEFINE(GOA_KERBEROS_NAME, ["kerberos"], [ProviderType and extension point name])
AC_ARG_ENABLE([kerberos],
......@@ -544,7 +526,6 @@ echo "
Kerberos provider: ${enable_kerberos}
Facebook provider: ${enable_facebook} (OAuth 2.0, id:${with_facebook_client_id})
Windows Live provider: ${enable_windows_live} (OAuth 2.0, id:${with_windows_live_client_id})
Pocket provider: ${enable_pocket} (id:${with_pocket_client_id})
Last.fm provider: ${enable_lastfm} (id:${with_lastfm_client_id} secret:${with_lastfm_client_secret})
Maintainer mode: ${USE_MAINTAINER_MODE}
......
......@@ -813,8 +813,12 @@
An account object implements this interface if it provides
read-later-like capabilities.
The #org.gnome.OnlineAccounts.Todo interface is not used by
any account.
-->
<interface name="org.gnome.OnlineAccounts.ReadLater">
<annotation name="org.freedesktop.DBus.Deprecated" value="true"/>
</interface>
<!--
......
......@@ -4,8 +4,7 @@ icon_scalable_data = [
'goa-account-foursquare.svg',
'goa-account-google.svg',
'goa-account-msn.svg',
'goa-account-owncloud.svg',
'goa-account-pocket.svg',
'goa-account-owncloud.svg'
]
icon_symbolic_data = [
......@@ -15,7 +14,6 @@ icon_symbolic_data = [
'goa-account-google-symbolic.svg',
'goa-account-msn-symbolic.svg',
'goa-account-owncloud-symbolic.svg',
'goa-account-pocket-symbolic.svg',
]
icons = [
......
......@@ -12,7 +12,7 @@
<description xml:lang="en">
GNOME Online Accounts provides interfaces so that applications and
libraries in GNOME can access the user's online accounts. It has
providers for Google, Nextcloud, Facebook, Microsoft, Flickr, Pocket,
providers for Google, Nextcloud, Facebook, Microsoft, Flickr,
Foursquare, Microsoft Exchange, Last.fm, IMAP/SMTP and Kerberos.
</description>
......
......@@ -207,15 +207,6 @@ config_h.set_quoted('GOA_OWNCLOUD_NAME', 'owncloud')
enable_owncloud = get_option('owncloud')
config_h.set('GOA_OWNCLOUD_ENABLED', enable_owncloud)
# Pocket
config_h.set_quoted('GOA_POCKET_NAME', 'pocket')
pocket_client_id = get_option('pocket_client_id')
config_h.set_quoted('GOA_POCKET_CLIENT_ID', pocket_client_id)
enable_pocket = get_option('pocket')
config_h.set('GOA_POCKET_ENABLED', enable_pocket)
# Windows Live
config_h.set_quoted('GOA_WINDOWS_LIVE_NAME', 'windows_live')
......@@ -338,10 +329,6 @@ output += '\n'
output += ' Media Server provider: ' + enable_media_server.to_string() + '\n'
output += ' Microsoft Exchange provider: ' + enable_exchange.to_string() + '\n'
output += ' ownCloud provider: ' + enable_owncloud.to_string() + '\n'
output += ' Pocket provider: ' + enable_pocket.to_string()
if enable_pocket
output += ' (id:@0@)'.format(pocket_client_id)
endif
output += '\n'
output += ' Windows Live provider: ' + enable_windows_live.to_string()
if enable_windows_live
......
......@@ -29,9 +29,6 @@ option('media_server', type: 'boolean', value: false, description: 'Enable Media
option('owncloud', type: 'boolean', value: true, description: 'Enable ownCloud provider')
option('pocket', type: 'boolean', value: true, description: 'Enable Pocket provider')
option('pocket_client_id', type: 'string', value: '16630-40b25246b56e8ad5310b2883', description: 'Pocket OAuth 2.0 client id')
option('windows_live', type: 'boolean', value: true, description: 'Enable Windows Live provider')
option('windows_live_client_id', type: 'string', value: '0000000044067703', description: 'Windows Live OAuth 2.0 client id')
......
......@@ -16,7 +16,6 @@ src/goabackend/goamediaserverprovider.c
src/goabackend/goaoauth2provider.c
src/goabackend/goaoauthprovider.c
src/goabackend/goaowncloudprovider.c
src/goabackend/goapocketprovider.c
src/goabackend/goaprovider.c
src/goabackend/goasmtpauth.c
src/goabackend/goautils.c
......
......@@ -27,7 +27,7 @@ lastfm_shout_LDADD = $(GLIB_LIBS) $(REST_LIBS) ../goa/libgoa-1.0.la
lastfm_shout_LDFLAGS = $(WARN_LDFLAGS)
if BUILD_BACKEND
noinst_PROGRAMS += introspect-providers list-providers add-pocket
noinst_PROGRAMS += introspect-providers list-providers
introspect_providers_SOURCES = introspect-providers.c
introspect_providers_CFLAGS = $(GLIB_CFLAGS) $(GTK_CFLAGS)
......@@ -38,11 +38,6 @@ list_providers_SOURCES = list-providers.c
list_providers_CFLAGS = $(GLIB_CFLAGS) $(GTK_CFLAGS)
list_providers_LDADD = $(GLIB_LIBS) $(GTK_LIBS) ../goabackend/libgoa-backend-1.0.la ../goa/libgoa-1.0.la
list_providers_LDFLAGS = $(WARN_LDFLAGS)
add_pocket_SOURCES = add-pocket.c
add_pocket_CFLAGS = $(GLIB_CFLAGS) $(REST_CFLAGS)
add_pocket_LDADD = $(GLIB_LIBS) $(REST_LIBS) ../goa/libgoa-1.0.la
add_pocket_LDFLAGS = $(WARN_LDFLAGS)
endif
clean-local :
......
/*
* Copyright © 2013 Bastien Nocera <hadess@hadess.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#define GOA_API_IS_SUBJECT_TO_CHANGE
#include <goa/goa.h>
#include <locale.h>
#include <rest/rest-proxy.h>
#include <rest/rest-proxy-call.h>
int
main (int argc, char **argv)
{
GError *error = NULL;
GoaClient *client;
GList *accounts, *l;
GoaAccount *account = NULL;
GoaOAuth2Based *oauth2 = NULL;
char *access_token = NULL;
RestProxy *proxy;
RestProxyCall *call;
const char *url;
const char *tweet_id = NULL;
setlocale (LC_ALL, "");
if (argc != 2 && argc != 3) {
g_print ("Usage: %s URL [TWEET ID]\n", argv[0]);
return 1;
}
url = argv[1];
if (argv[2] != NULL)
tweet_id = argv[2];
client = goa_client_new_sync (NULL, &error);
if (!client) {
g_error ("Could not create GoaClient: %s", error->message);
return 1;
}
accounts = goa_client_get_accounts (client);
/* Find a Pocket account */
for (l = accounts; l != NULL; l = l->next) {
GoaObject *object = GOA_OBJECT (l->data);
account = goa_object_peek_account (object);
if (g_strcmp0 (goa_account_get_provider_type (account), "pocket") == 0) {
g_object_ref (account);
oauth2 = goa_object_get_oauth2_based (object);
break;
}
}
g_list_free_full (accounts, (GDestroyNotify) g_object_unref);
g_assert (account);
g_assert (oauth2);
if (!goa_oauth2_based_call_get_access_token_sync (oauth2, &access_token, NULL, NULL, &error)) {
g_error ("Could not get access token: %s", error->message);
return 1;
}
g_print ("Got access tokens\n");
proxy = rest_proxy_new ("https://getpocket.com/", FALSE);
call = rest_proxy_new_call (proxy);
rest_proxy_call_set_method (call, "POST");
rest_proxy_call_set_function (call, "v3/add");
rest_proxy_call_add_param (call, "consumer_key", goa_oauth2_based_get_client_id (oauth2));
rest_proxy_call_add_param (call, "access_token", access_token);
rest_proxy_call_add_param (call, "url", url);
if (tweet_id)
rest_proxy_call_add_param (call, "tweet_id", tweet_id);
g_print ("Adding to Pocket...\n");
if (!rest_proxy_call_sync (call, &error)) {
g_error ("Cannot add to Pocket: %s", error->message);
return 1;
}
g_print ("Added!\n");
return 0;
}
......@@ -8,7 +8,6 @@ if enable_goabackend
programs += [
['introspect-providers', libgoa_backend_dep],
['list-providers', libgoa_backend_dep],
['add-pocket', [libgoa_dep, rest_dep]]
]
endif
......
......@@ -92,7 +92,6 @@ libgoa_backend_1_0_la_SOURCES = \
goaflickrprovider.h goaflickrprovider.c \
goafoursquareprovider.h goafoursquareprovider.c \
goawindowsliveprovider.h goawindowsliveprovider.c \
goapocketprovider.h goapocketprovider.c \
goalastfmprovider.h goalastfmprovider.c \
goaobjectskeletonutils.h goaobjectskeletonutils.c \
goautils.h goautils.c \
......
......@@ -67,7 +67,7 @@ typedef enum
* @GOA_PROVIDER_FEATURE_PHOTOS: Photos storage services (ie. Flickr).
* @GOA_PROVIDER_FEATURE_FILES: Files storage services (ie. WebDAV).
* @GOA_PROVIDER_FEATURE_TICKETING: Ticketing services (ie. Kerberos).
* @GOA_PROVIDER_FEATURE_READ_LATER: Read later services (eg. Pocket).
* @GOA_PROVIDER_FEATURE_READ_LATER: Deprecated; currently unused.
* @GOA_PROVIDER_FEATURE_PRINTERS: Network printing services (e.g. Google Cloud Print).
* @GOA_PROVIDER_FEATURE_MAPS: Maps related services (e.g. Foursquare, Facebook).
* @GOA_PROVIDER_FEATURE_MUSIC: Music related services (e.g. Vkontakte).
......
......@@ -203,26 +203,3 @@ goa_object_skeleton_attach_maps (GoaObjectSkeleton *object,
}
g_clear_object (&maps);
}
void
goa_object_skeleton_attach_read_later (GoaObjectSkeleton *object,
gboolean read_later_enabled)
{
GoaReadLater *readlater = NULL;
readlater = goa_object_get_read_later (GOA_OBJECT (object));
if (read_later_enabled)
{
if (readlater == NULL)
{
readlater = goa_read_later_skeleton_new ();
goa_object_skeleton_set_read_later (object, readlater);
}
}
else
{
if (readlater != NULL)
goa_object_skeleton_set_read_later (object, NULL);
}
g_clear_object (&readlater);
}
......@@ -55,9 +55,6 @@ void goa_object_skeleton_attach_photos (GoaObjectSkeleton *o
void goa_object_skeleton_attach_printers (GoaObjectSkeleton *object,
gboolean printers_enabled);
void goa_object_skeleton_attach_read_later (GoaObjectSkeleton *object,
gboolean read_later_enabled);
G_END_DECLS
#endif /* __GOA_OBJECT_SKELETON_UTILS_H__ */
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright © 2013 – 2017 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib/gi18n-lib.h>
#include <rest/rest-proxy.h>
#include <json-glib/json-glib.h>
#include <libsoup/soup.h>
#include "goaprovider.h"
#include "goaprovider-priv.h"
#include "goaoauth2provider.h"
#include "goaoauth2provider-priv.h"
#include "goapocketprovider.h"
#include "goaobjectskeletonutils.h"
#include "goarestproxy.h"
#define V3_OAUTH_AUTHORIZE_URL "https://getpocket.com/v3/oauth/authorize"
struct _GoaPocketProvider
{
GoaOAuth2Provider parent_instance;
gchar *authorization_uri;
/* request token as gathered from Step 2:
* http://getpocket.com/developer/docs/authentication */
gchar *code;
gchar *identity;
};
typedef struct _GoaPocketProviderClass GoaPocketProviderClass;
struct _GoaPocketProviderClass
{
GoaOAuth2ProviderClass parent_class;
};
G_DEFINE_TYPE_WITH_CODE (GoaPocketProvider, goa_pocket_provider, GOA_TYPE_OAUTH2_PROVIDER,
goa_provider_ensure_extension_points_registered ();
g_io_extension_point_implement (GOA_PROVIDER_EXTENSION_POINT_NAME,
g_define_type_id,
GOA_POCKET_NAME,
0));
/* ---------------------------------------------------------------------------------------------------- */
static const gchar *
get_provider_type (GoaProvider *provider)
{
return GOA_POCKET_NAME;
}
static gchar *
get_provider_name (GoaProvider *provider,
GoaObject *object)
{
return g_strdup (_("Pocket"));
}
static GoaProviderGroup
get_provider_group (GoaProvider *provider)
{
return GOA_PROVIDER_GROUP_BRANDED;
}
static GoaProviderFeatures
get_provider_features (GoaProvider *provider)
{
return GOA_PROVIDER_FEATURE_BRANDED |
GOA_PROVIDER_FEATURE_READ_LATER;
}
static const gchar *
get_request_uri (GoaOAuth2Provider *oauth2_provider)
{
return "https://getpocket.com/v3/oauth/request";
}
static const gchar *
get_authorization_uri (GoaOAuth2Provider *oauth2_provider)
{
return "https://getpocket.com/auth/authorize";
}
static const gchar *
get_token_uri (GoaOAuth2Provider *oauth2_provider)
{
return NULL;
}
static const gchar *
get_redirect_uri (GoaOAuth2Provider *oauth2_provider)
{
return "https://localhost";
}
static const gchar *
get_client_id (GoaOAuth2Provider *oauth2_provider)
{
return GOA_POCKET_CLIENT_ID;
}
static const gchar *
get_client_secret (GoaOAuth2Provider *oauth2_provider)
{
return NULL;
}
static gchar *
build_authorization_uri (GoaOAuth2Provider *oauth2_provider,
const gchar *authorization_uri,
const gchar *escaped_redirect_uri,
const gchar *escaped_client_id,
const gchar *escaped_scope)
{
GoaPocketProvider *self = GOA_POCKET_PROVIDER (oauth2_provider);
RestProxy *proxy = NULL;
RestProxyCall *call = NULL;
const gchar *payload;
gchar *code, *url = NULL;
GError *error = NULL;
GHashTable *hash;
if (self->authorization_uri != NULL)
goto end;
proxy = goa_rest_proxy_new (get_request_uri (oauth2_provider), FALSE);
call = rest_proxy_new_call (proxy);
rest_proxy_call_set_method (call, "POST");
rest_proxy_call_add_header (call, "Content-Type", "application/x-www-form-urlencoded");
rest_proxy_call_add_param (call, "consumer_key", GOA_POCKET_CLIENT_ID);
rest_proxy_call_add_param (call, "redirect_uri", get_redirect_uri (oauth2_provider));
if (!rest_proxy_call_sync (call, &error))
{
g_debug ("Call to %s failed: %s", get_redirect_uri (oauth2_provider), error->message);
g_error_free (error);
goto out;
}
payload = rest_proxy_call_get_payload (call);
hash = soup_form_decode (payload);
code = g_strdup (g_hash_table_lookup (hash, "code"));
g_hash_table_unref (hash);
if (!code)
{
g_debug ("Failed to get code from answer to %s", get_redirect_uri (oauth2_provider));
goto out;
}
self->authorization_uri = g_strdup_printf ("%s"
"?request_token=%s"
"&redirect_uri=%s",
authorization_uri,
code,
escaped_redirect_uri);
self->code = code;
end:
url = g_strdup (self->authorization_uri);
out:
g_clear_object (&call);
g_clear_object (&proxy);
return url;
}
static gboolean
decide_navigation_policy (GoaOAuth2Provider *oauth2_provider,
WebKitWebView *web_view,
WebKitNavigationPolicyDecision *decision)
{
GoaPocketProvider *self = GOA_POCKET_PROVIDER (oauth2_provider);
WebKitNavigationAction *action;
WebKitURIRequest *request;
gboolean ret = FALSE;
const gchar *uri;
action = webkit_navigation_policy_decision_get_navigation_action (decision);
request = webkit_navigation_action_get_request (action);
uri = webkit_uri_request_get_uri (request);
if (!g_str_has_prefix (uri, "https://getpocket.com/a/"))
goto out;
webkit_uri_request_set_uri (request, self->authorization_uri);
webkit_web_view_load_request (web_view, request);
ret = TRUE;
out:
return ret;
}
static gboolean
process_redirect_url (GoaOAuth2Provider *oauth2_provider,
const gchar *redirect_url,
gchar **access_token,
GError **error)
{
GoaPocketProvider *self = GOA_POCKET_PROVIDER (oauth2_provider);
RestProxy *proxy;
RestProxyCall *call;
GHashTable *hash;
const gchar *payload;
gboolean ret = FALSE;
proxy = goa_rest_proxy_new (V3_OAUTH_AUTHORIZE_URL, FALSE);
call = rest_proxy_new_call (proxy);
rest_proxy_call_set_method (call, "POST");
rest_proxy_call_add_header (call, "Content-Type", "application/x-www-form-urlencoded");
rest_proxy_call_add_param (call, "consumer_key", GOA_POCKET_CLIENT_ID);
rest_proxy_call_add_param (call, "code", self->code);
if (!rest_proxy_call_sync (call, error))
goto out;
payload = rest_proxy_call_get_payload (call);
hash = soup_form_decode (payload);
self->identity = g_strdup (g_hash_table_lookup (hash, "username"));
*access_token = g_strdup (g_hash_table_lookup (hash, "access_token"));
g_hash_table_unref (hash);
if (self->identity == NULL|| *access_token == NULL)
{
g_set_error (error,
GOA_ERROR,
GOA_ERROR_FAILED, /* TODO: more specific */
_("No username or access_token"));
g_clear_pointer (&self->identity, g_free);
g_clear_pointer (access_token, g_free);
goto out;
}
ret = TRUE;
out:
g_clear_object (&call);
g_clear_object (&proxy);
return ret;
}
/* ---------------------------------------------------------------------------------------------------- */
static gchar *
get_identity_sync (GoaOAuth2Provider *oauth2_provider,
const gchar *access_token,
gchar **out_presentation_identity,
GCancellable *cancellable,
GError **error)
{
GoaPocketProvider *self = GOA_POCKET_PROVIDER (oauth2_provider);
if (out_presentation_identity != NULL)
*out_presentation_identity = g_strdup (self->identity);
if (!self->identity)
g_set_error (error, GOA_ERROR, GOA_ERROR_FAILED, "Identity is saved to disk already");
return g_strdup (self->identity);
}
/* ---------------------------------------------------------------------------------------------------- */
static gboolean
is_deny_node (GoaOAuth2Provider *oauth2_provider, WebKitDOMNode *node)
{
WebKitDOMElement *element;
gboolean ret = FALSE;
gchar *id = NULL;
gchar *class = NULL;
gchar *text = NULL;
if (!WEBKIT_DOM_IS_ELEMENT (node))