[epiphany/wip/ephy-sync: 123/126] sync-service: Move here the actual sync functions
- From: Gabriel - Cristian Ivascu <gabrielivascu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/wip/ephy-sync: 123/126] sync-service: Move here the actual sync functions
- Date: Fri, 19 Aug 2016 17:41:54 +0000 (UTC)
commit 12a491660f649188506bd134bead45a217f748ae
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date: Tue Aug 16 02:32:10 2016 +0300
sync-service: Move here the actual sync functions
src/Makefile.am | 2 -
src/ephy-sync-bookmarks.c | 352 ---------------------------------------------
src/ephy-sync-bookmarks.h | 38 -----
src/ephy-sync-service.c | 330 ++++++++++++++++++++++++++++++++++++++++++
src/ephy-sync-service.h | 70 +++++----
src/prefs-dialog.c | 3 +-
6 files changed, 370 insertions(+), 425 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index a69db75..c42111e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -69,8 +69,6 @@ libephymain_la_SOURCES = \
ephy-session.h \
ephy-shell.c \
ephy-shell.h \
- ephy-sync-bookmarks.c \
- ephy-sync-bookmarks.h \
ephy-sync-crypto.c \
ephy-sync-crypto.h \
ephy-sync-secret.c \
diff --git a/src/ephy-sync-service.c b/src/ephy-sync-service.c
index 07ce082..b865751 100644
--- a/src/ephy-sync-service.c
+++ b/src/ephy-sync-service.c
@@ -19,8 +19,11 @@
#include "config.h"
#include "ephy-sync-service.h"
+#include "ephy-bookmark.h"
+#include "ephy-bookmarks-manager.h"
#include "ephy-debug.h"
#include "ephy-settings.h"
+#include "ephy-shell.h"
#include "ephy-sync-crypto.h"
#include "ephy-sync-secret.h"
@@ -29,6 +32,10 @@
#define MOZILLA_TOKEN_SERVER_URL "https://token.services.mozilla.com/1.0/sync/1.5"
#define MOZILLA_FXA_SERVER_URL "https://api.accounts.firefox.com/v1/"
+
+#define DUMMY_BOOKMARK_ID "00000000000000000000000000000000"
+#define EPHY_BOOKMARKS_COLLECTION "ephy-bookmarks"
+
#define EMAIL_REGEX "^[a-zA-Z0-9_]([a-zA-Z0-9._]+[a-zA-Z0-9_])?@[a-z0-9.-]+$"
struct _EphySyncService {
@@ -906,3 +913,326 @@ ephy_sync_service_release_next_storage_message (EphySyncService *self)
else
self->is_locked = FALSE;
}
+
+static void
+log_all_message_info (const gchar *text,
+ SoupMessage *message)
+{
+ LOG ("%s:", text);
+ LOG ("status_code: %u", message->status_code);
+ LOG ("response_body: %s", message->response_body->data);
+ LOG ("Retry-After: %s", soup_message_headers_get_one (message->response_headers, "Retry-After"));
+ LOG ("X-Weave-Backoff: %s", soup_message_headers_get_one (message->response_headers, "X-Weave-Backoff"));
+ LOG ("X-Last-Modified: %s", soup_message_headers_get_one (message->response_headers, "X-Last-Modified"));
+ LOG ("X-Weave-Timestamp: %s", soup_message_headers_get_one (message->response_headers,
"X-Weave-Timestamp"));
+ LOG ("X-Weave-Records: %s", soup_message_headers_get_one (message->response_headers, "X-Weave-Records"));
+ LOG ("X-Weave-Next-Offset: %s", soup_message_headers_get_one (message->response_headers,
"X-Weave-Next-Offset"));
+ LOG ("X-Weave-Quota-Remaining: %s", soup_message_headers_get_one (message->response_headers,
"X-Weave-Quota-Remaining"));
+ LOG ("X-Weave-Alert: %s", soup_message_headers_get_one (message->response_headers, "X-Weave-Alert"));
+}
+
+static void
+create_bookmarks_storage_collection_response_cb (SoupSession *session,
+ SoupMessage *message,
+ gpointer user_data)
+{
+ EphySyncService *service;
+
+ /* Code 412 means that the BSO already exists. Don't treat this as an error. */
+ if (message->status_code != 200 && message->status_code != 412)
+ LOG ("Failed to add the dummy BSO. Status code: %u, response: %s",
+ message->status_code, message->response_body->data);
+
+ service = ephy_shell_get_global_sync_service (ephy_shell_get_default ());
+ ephy_sync_service_release_next_storage_message (service);
+}
+
+void
+ephy_sync_service_create_bookmarks_storage_collection (EphySyncService *self)
+{
+ EphyBookmark *dummy;
+ gchar *endpoint;
+ gchar *bso;
+
+ g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+ g_return_if_fail (ephy_sync_service_is_signed_in (self));
+
+ endpoint = g_strdup_printf ("storage/%s/%s", EPHY_BOOKMARKS_COLLECTION, DUMMY_BOOKMARK_ID);
+ dummy = ephy_bookmark_new (g_strdup (DUMMY_BOOKMARK_ID),
+ g_strdup (DUMMY_BOOKMARK_ID),
+ g_sequence_new (g_free));
+ ephy_bookmark_set_id (dummy, DUMMY_BOOKMARK_ID);
+ bso = ephy_bookmark_to_bso (dummy);
+
+ /* Send a dummy BSO to the Storage Server so it will create the
+ * EPHY_BOOKMARKS_COLLECTION collection if it doesn't exist already.
+ */
+ ephy_sync_service_send_storage_message (self, endpoint, SOUP_METHOD_PUT,
+ bso, -1, 0,
+ create_bookmarks_storage_collection_response_cb, NULL);
+
+ g_free (endpoint);
+ g_free (bso);
+}
+
+static void
+upload_bookmark_to_server_response_cb (SoupSession *session,
+ SoupMessage *message,
+ gpointer user_data)
+{
+ EphySyncService *service;
+ EphyBookmarksManager *manager;
+ EphyBookmark *bookmark;
+ double last_modified;
+
+ if (message->status_code == 200) {
+ bookmark = EPHY_BOOKMARK (user_data);
+ last_modified = g_ascii_strtod (message->response_body->data, NULL);
+ ephy_bookmark_set_modified (bookmark, last_modified);
+ manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
+ ephy_bookmarks_manager_save_to_file_async (manager, NULL, NULL, NULL);
+
+ LOG ("Successfully uploaded bookmark to server.");
+ } else if (message->status_code == 412) {
+ /* FIXME: A more recent value is on the server. See how to handle this. */
+ } else {
+ LOG ("Failed to upload bookmark to the server. Status code: %u, response: %s",
+ message->status_code, message->response_body->data);
+ }
+
+ service = ephy_shell_get_global_sync_service (ephy_shell_get_default ());
+ ephy_sync_service_release_next_storage_message (service);
+}
+
+void
+ephy_sync_service_upload_bookmark_to_server (EphySyncService *self,
+ EphyBookmark *bookmark,
+ gboolean force)
+{
+ gchar *endpoint;
+ gchar *bso;
+ double modified;
+
+ g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+ g_return_if_fail (ephy_sync_service_is_signed_in (self));
+ g_return_if_fail (EPHY_IS_BOOKMARK (bookmark));
+
+ endpoint = g_strdup_printf ("storage/%s/%s",
+ EPHY_BOOKMARKS_COLLECTION,
+ ephy_bookmark_get_id (bookmark));
+ bso = ephy_bookmark_to_bso (bookmark);
+ modified = ephy_bookmark_get_modified (bookmark);
+ ephy_sync_service_send_storage_message (self, endpoint,
+ SOUP_METHOD_PUT, bso, -1,
+ force ? -1 : modified,
+ upload_bookmark_to_server_response_cb,
+ bookmark);
+
+ g_free (endpoint);
+ g_free (bso);
+}
+
+static void
+merge_local_and_remote_bookmarks_response_cb (SoupSession *session,
+ SoupMessage *message,
+ gpointer user_data)
+{
+ EphySyncService *service;
+ EphyBookmarksManager *manager;
+ GSequence *bookmarks;
+ JsonParser *parser;
+ JsonArray *array;
+ GList *remotes = NULL;
+ GList *locals = NULL;
+ gboolean *marked_locals = NULL;
+ gboolean *marked_remotes = NULL;
+ gsize i;
+
+ service = ephy_shell_get_global_sync_service (ephy_shell_get_default ());
+ manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
+ bookmarks = ephy_bookmarks_manager_get_bookmarks (manager);
+ parser = json_parser_new ();
+ json_parser_load_from_data (parser, message->response_body->data, -1, NULL);
+ array = json_node_get_array (json_parser_get_root (parser));
+
+ /* Convert all BSOs to EphyBookmark objects. */
+ for (i = 0; i < json_array_get_length (array); i++) {
+ JsonObject *bso = json_array_get_object_element (array, i);
+ EphyBookmark *bookmark = ephy_bookmark_from_bso (bso);
+
+ if (g_strcmp0 (ephy_bookmark_get_id (bookmark), DUMMY_BOOKMARK_ID) == 0) {
+ g_object_unref (bookmark);
+ continue;
+ }
+
+ remotes = g_list_append (remotes, bookmark);
+ }
+
+ /* If we have no remote bookmarks, then we directly upload all the local
+ * bookmarks to the server.
+ */
+ if (g_list_length (remotes) == 0) {
+ for (GSequenceIter *iter = g_sequence_get_begin_iter (bookmarks);
+ !g_sequence_iter_is_end (iter); iter = g_sequence_iter_next (iter))
+ ephy_sync_service_upload_bookmark_to_server (service, g_sequence_get (iter), TRUE);
+ goto out;
+ }
+
+ /* If we have no local bookmarks, then we add all the remote bookmarks to the
+ * local instance.
+ */
+ if (g_sequence_is_empty (bookmarks) == TRUE) {
+ for (GList *r = remotes; r != NULL; r = r->next)
+ ephy_bookmarks_manager_add_bookmark (manager, EPHY_BOOKMARK (r->data));
+ goto out;
+ }
+
+ /* If we have both local and remote bookmarks, then we merge them in the
+ * nicest way possible (see the two cases below).
+ */
+ for (GSequenceIter *iter = g_sequence_get_begin_iter (bookmarks);
+ !g_sequence_iter_is_end (iter); iter = g_sequence_iter_next (iter))
+ locals = g_list_append (locals, g_sequence_get (iter));
+
+ marked_locals = g_malloc0 (g_list_length (locals) * sizeof (gboolean));
+ marked_remotes = g_malloc0 (g_list_length (remotes) * sizeof (gboolean));
+
+ i = 0;
+ for (GList *l = locals; l != NULL; l = l->next, i++) {
+ EphyBookmark *local = EPHY_BOOKMARK (l->data);
+ const gchar *local_id = ephy_bookmark_get_id (local);
+ double local_modified = ephy_bookmark_get_modified (local);
+ const gchar *local_url = ephy_bookmark_get_url (local);
+ gsize j = 0;
+
+ for (GList *r = remotes; r != NULL; r = r->next, j++) {
+ if (marked_remotes[j] == FALSE) {
+ EphyBookmark *remote = EPHY_BOOKMARK (r->data);
+ const gchar *remote_id = ephy_bookmark_get_id (remote);
+ double remote_modified = ephy_bookmark_get_modified (remote);
+ const gchar *remote_url = ephy_bookmark_get_url (remote);
+
+ /* Case 1: same ids.
+ * Since ids are globally unique, having a bookmark on the server with
+ * the same id means that the bookmark has been synced before in the
+ * past. Keep the one with most recent modified timestamp.
+ */
+ if (g_strcmp0 (local_id, remote_id) == 0) {
+ if (local_modified > remote_modified) {
+ ephy_sync_service_upload_bookmark_to_server (service, local, TRUE);
+ } else if (remote_modified > local_modified) {
+ ephy_bookmarks_manager_remove_bookmark (manager, local);
+ ephy_bookmarks_manager_add_bookmark (manager, remote);
+ } else {
+ g_object_unref (remote);
+ }
+ marked_locals[i] = marked_remotes[j] = TRUE;
+ break;
+ }
+
+ /* Case 2: different ids, same urls.
+ * Merge tags into the local bookmark, keep the remote id and upload it
+ * to server. The add_tag functions will ignore the duplicates themselves.
+ */
+ if (g_strcmp0 (local_url, remote_url) == 0) {
+ GSequence *tags = ephy_bookmark_get_tags (remote);
+
+ for (GSequenceIter *it = g_sequence_get_begin_iter (tags);
+ !g_sequence_iter_is_end (it); it = g_sequence_iter_next (it)) {
+ const gchar *tag = g_sequence_get (it);
+ ephy_bookmark_add_tag (local, tag);
+ ephy_bookmarks_manager_add_tag (manager, tag);
+ }
+
+ ephy_bookmark_set_id (local, remote_id);
+ ephy_sync_service_upload_bookmark_to_server (service, local, TRUE);
+ g_object_unref (remote);
+ marked_locals[i] = marked_remotes[j] = TRUE;
+ break;
+ }
+ }
+ }
+ }
+
+ /* The remaining unmarked local bookmarks will be directly uploaded to the server. */
+ i = 0;
+ for (GList *l = locals; l != NULL; l = l->next, i++)
+ if (marked_locals[i] == FALSE)
+ ephy_sync_service_upload_bookmark_to_server (service, EPHY_BOOKMARK (l->data), TRUE);
+
+ /* The remaining unmarked remote bookmarks will be added to the local instance. */
+ i = 0;
+ for (GList *r = remotes; r != NULL; r = r->next, i++)
+ if (marked_remotes[i] == FALSE)
+ ephy_bookmarks_manager_add_bookmark (manager, EPHY_BOOKMARK (r->data));
+
+ /* Save changes to file. */
+ ephy_bookmarks_manager_save_to_file_async (manager, NULL, NULL, NULL);
+
+ out:
+ g_object_unref (parser);
+ g_list_free (locals);
+ g_list_free (remotes);
+ g_free (marked_locals);
+ g_free (marked_remotes);
+
+ ephy_sync_service_release_next_storage_message (service);
+}
+
+void
+ephy_sync_service_merge_local_and_remote_bookmarks (EphySyncService *self)
+{
+ gchar *endpoint;
+
+ g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+ g_return_if_fail (ephy_sync_service_is_signed_in (self));
+
+ endpoint = g_strdup_printf ("storage/%s?full=true", EPHY_BOOKMARKS_COLLECTION);
+ ephy_sync_service_send_storage_message (self, endpoint,
+ SOUP_METHOD_GET, NULL, -1, -1,
+ merge_local_and_remote_bookmarks_response_cb, NULL);
+ g_free (endpoint);
+}
+
+static void
+storage_server_response_default_cb (SoupSession *session,
+ SoupMessage *message,
+ gpointer user_data)
+{
+ EphySyncService *service;
+
+ log_all_message_info ("storage_server_response_default_cb", message);
+
+ service = ephy_shell_get_global_sync_service (ephy_shell_get_default ());
+ ephy_sync_service_release_next_storage_message (service);
+}
+
+void
+ephy_sync_service_check_bookmarks_storage_collection (EphySyncService *self)
+{
+ gchar *endpoint;
+
+ g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+ g_return_if_fail (ephy_sync_service_is_signed_in (self));
+
+ endpoint = g_strdup_printf ("storage/%s", EPHY_BOOKMARKS_COLLECTION);
+ ephy_sync_service_send_storage_message (self, endpoint,
+ SOUP_METHOD_GET, NULL, -1, -1,
+ storage_server_response_default_cb, NULL);
+ g_free (endpoint);
+}
+
+void
+ephy_sync_service_delete_bookmarks_storage_collection (EphySyncService *self)
+{
+ gchar *endpoint;
+
+ g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+ g_return_if_fail (ephy_sync_service_is_signed_in (self));
+
+ endpoint = g_strdup_printf ("storage/%s", EPHY_BOOKMARKS_COLLECTION);
+ ephy_sync_service_send_storage_message (self, endpoint,
+ SOUP_METHOD_DELETE, NULL, -1, -1,
+ storage_server_response_default_cb, NULL);
+ g_free (endpoint);
+}
diff --git a/src/ephy-sync-service.h b/src/ephy-sync-service.h
index d0a27f5..3246f70 100644
--- a/src/ephy-sync-service.h
+++ b/src/ephy-sync-service.h
@@ -19,6 +19,7 @@
#ifndef EPHY_SYNC_SERVICE_H
#define EPHY_SYNC_SERVICE_H
+#include "ephy-bookmark.h"
#include "ephy-sync-utils.h"
#include <glib-object.h>
@@ -30,37 +31,44 @@ G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (EphySyncService, ephy_sync_service, EPHY, SYNC_SERVICE, GObject)
-EphySyncService *ephy_sync_service_new (void);
-gboolean ephy_sync_service_is_signed_in (EphySyncService *self);
-gchar *ephy_sync_service_get_user_email (EphySyncService *self);
-void ephy_sync_service_set_user_email (EphySyncService *self,
- const gchar *email);
-gchar *ephy_sync_service_get_token (EphySyncService *self,
- EphySyncTokenType type);
-void ephy_sync_service_set_token (EphySyncService *self,
- gchar *value,
- EphySyncTokenType type);
-void ephy_sync_service_set_and_store_tokens (EphySyncService *self,
- gchar *value,
- EphySyncTokenType type,
- ...) G_GNUC_NULL_TERMINATED;
-void ephy_sync_service_clear_storage_credentials (EphySyncService *self);
-void ephy_sync_service_clear_tokens (EphySyncService *self);
-void ephy_sync_service_destroy_session (EphySyncService *self,
- const gchar *sessionToken);
-gboolean ephy_sync_service_fetch_sync_keys (EphySyncService *self,
- const gchar *email,
- const gchar *keyFetchToken,
- const gchar *unwrapBKey);
-void ephy_sync_service_send_storage_message (EphySyncService *self,
- gchar *endpoint,
- const gchar *method,
- gchar *request_body,
- double modified_since,
- double unmodified_since,
- SoupSessionCallback callback,
- gpointer user_data);
-void ephy_sync_service_release_next_storage_message (EphySyncService *self);
+EphySyncService *ephy_sync_service_new (void);
+gboolean ephy_sync_service_is_signed_in (EphySyncService *self);
+gchar *ephy_sync_service_get_user_email (EphySyncService *self);
+void ephy_sync_service_set_user_email (EphySyncService *self,
+ const gchar *email);
+gchar *ephy_sync_service_get_token (EphySyncService *self,
+ EphySyncTokenType type);
+void ephy_sync_service_set_token (EphySyncService *self,
+ gchar *value,
+ EphySyncTokenType type);
+void ephy_sync_service_set_and_store_tokens (EphySyncService *self,
+ gchar *value,
+ EphySyncTokenType type,
+ ...) G_GNUC_NULL_TERMINATED;
+void ephy_sync_service_clear_storage_credentials (EphySyncService *self);
+void ephy_sync_service_clear_tokens (EphySyncService *self);
+void ephy_sync_service_destroy_session (EphySyncService *self,
+ const gchar *sessionToken);
+gboolean ephy_sync_service_fetch_sync_keys (EphySyncService *self,
+ const gchar *email,
+ const gchar *keyFetchToken,
+ const gchar *unwrapBKey);
+void ephy_sync_service_send_storage_message (EphySyncService *self,
+ gchar *endpoint,
+ const gchar *method,
+ gchar *request_body,
+ double modified_since,
+ double
unmodified_since,
+ SoupSessionCallback callback,
+ gpointer user_data);
+void ephy_sync_service_release_next_storage_message (EphySyncService *self);
+void ephy_sync_service_create_bookmarks_storage_collection (EphySyncService *self);
+void ephy_sync_service_upload_bookmark_to_server (EphySyncService *self,
+ EphyBookmark *bookmark,
+ gboolean force);
+void ephy_sync_service_merge_local_and_remote_bookmarks (EphySyncService *self);
+void ephy_sync_service_check_bookmarks_storage_collection (EphySyncService *self);
+void ephy_sync_service_delete_bookmarks_storage_collection (EphySyncService *self);
G_END_DECLS
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index d1e719c..d473129 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -35,7 +35,6 @@
#include "ephy-session.h"
#include "ephy-settings.h"
#include "ephy-shell.h"
-#include "ephy-sync-bookmarks.h"
#include "ephy-sync-secret.h"
#include "ephy-sync-service.h"
#include "clear-data-dialog.h"
@@ -297,7 +296,7 @@ server_message_received_cb (WebKitUserContentManager *manager,
NULL);
/* Create our own bookmarks BSO collection on the Storage Server. */
- ephy_sync_bookmarks_create_storage_collection ();
+ ephy_sync_service_create_bookmarks_storage_collection (service);
/* Translators: the %s refers to the email of the currently logged in user. */
gtk_label_set_markup (GTK_LABEL (dialog->sync_sign_out_details),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]