[epiphany/wip/sync: 20/31] sync-service: Remove some circular dependencies between functions



commit a04c12122cad7a799f67abb2671646a2d0edeaef
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Wed Apr 12 19:22:57 2017 +0300

    sync-service: Remove some circular dependencies between functions

 src/sync/ephy-sync-service.c |  797 +++++++++++++++++++++---------------------
 1 files changed, 397 insertions(+), 400 deletions(-)
---
diff --git a/src/sync/ephy-sync-service.c b/src/sync/ephy-sync-service.c
index 7127632..096346d 100644
--- a/src/sync/ephy-sync-service.c
+++ b/src/sync/ephy-sync-service.c
@@ -122,9 +122,6 @@ typedef struct {
 } SyncAsyncData;
 
 static void ephy_sync_service_send_next_storage_request (EphySyncService *self);
-static void ephy_sync_service_stop_periodical_sync (EphySyncService *self);
-static void sync_frequency_changed_cb (EphySyncService *self);
-static void sync_secrets_store_finished_cb (EphySyncService *self, GError *error);
 
 static StorageRequestAsyncData *
 storage_request_async_data_new (const char          *endpoint,
@@ -472,6 +469,61 @@ out:
 }
 
 static void
+destroy_session_cb (SoupSession *session,
+                    SoupMessage *msg,
+                    gpointer     user_data)
+{
+  if (msg->status_code != 200)
+    g_warning ("Failed to destroy session. Status code: %u, response: %s",
+               msg->status_code, msg->response_body->data);
+  else
+    LOG ("Successfully destroyed session");
+}
+
+static void
+ephy_sync_service_destroy_session (EphySyncService *self)
+{
+  SyncCryptoHawkOptions *hoptions;
+  SyncCryptoHawkHeader *hheader;
+  SoupMessage *msg;
+  guint8 *tokenID;
+  guint8 *reqHMACkey;
+  guint8 *requestKey;
+  char *tokenID_hex;
+  char *url;
+  const char *content_type = "application/json";
+  const char *request_body = "{}";
+
+  g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+  g_return_if_fail (ephy_sync_service_get_secret (self, secrets[SESSION_TOKEN]));
+
+  url = g_strdup_printf ("%ssession/destroy", MOZILLA_FXA_SERVER_URL);
+  ephy_sync_crypto_process_session_token (ephy_sync_service_get_secret (self, secrets[SESSION_TOKEN]),
+                                          &tokenID, &reqHMACkey, &requestKey, TOKEN_LENGTH);
+  tokenID_hex = ephy_sync_crypto_encode_hex (tokenID, TOKEN_LENGTH);
+
+  msg = soup_message_new (SOUP_METHOD_POST, url);
+  soup_message_set_request (msg, content_type, SOUP_MEMORY_STATIC,
+                            request_body, strlen (request_body));
+  hoptions = ephy_sync_crypto_hawk_options_new (NULL, NULL, NULL, content_type,
+                                                NULL, NULL, NULL, request_body, NULL);
+  hheader = ephy_sync_crypto_compute_hawk_header (url, "POST", tokenID_hex,
+                                                  reqHMACkey, TOKEN_LENGTH,
+                                                  hoptions);
+  soup_message_headers_append (msg->request_headers, "authorization", hheader->header);
+  soup_message_headers_append (msg->request_headers, "content-type", content_type);
+  soup_session_queue_message (self->session, msg, destroy_session_cb, NULL);
+
+  ephy_sync_crypto_hawk_options_free (hoptions);
+  ephy_sync_crypto_hawk_header_free (hheader);
+  g_free (tokenID_hex);
+  g_free (tokenID);
+  g_free (reqHMACkey);
+  g_free (requestKey);
+  g_free (url);
+}
+
+static void
 obtain_storage_credentials_cb (SoupSession *session,
                                SoupMessage *msg,
                                gpointer     user_data)
@@ -827,6 +879,348 @@ ephy_sync_service_queue_storage_request (EphySyncService     *self,
 }
 
 static void
+download_synchronizable_cb (SoupSession *session,
+                            SoupMessage *msg,
+                            gpointer     user_data)
+{
+  EphySyncService *self;
+  EphySynchronizable *synchronizable;
+  SyncCryptoKeyBundle *bundle;
+  SyncAsyncData *data;
+  JsonNode *node;
+  GError *error = NULL;
+  GType type;
+  const char *collection;
+  gboolean is_deleted;
+
+  data = (SyncAsyncData *)user_data;
+  self = ephy_shell_get_sync_service (ephy_shell_get_default ());
+
+  if (msg->status_code != 200) {
+    g_warning ("Failed to download object. Status code: %u, response: %s",
+               msg->status_code, msg->response_body->data);
+    goto out;
+  }
+
+  node = json_from_string (msg->response_body->data, &error);
+  if (error) {
+    g_warning ("Response is not a valid JSON");
+    g_error_free (error);
+    goto out;
+  }
+
+  type = ephy_synchronizable_manager_get_synchronizable_type (data->manager);
+  collection = ephy_synchronizable_manager_get_collection_name (data->manager);
+  bundle = ephy_sync_service_get_key_bundle (self, collection);
+  synchronizable = EPHY_SYNCHRONIZABLE (ephy_synchronizable_from_bso (node, type, bundle, &is_deleted));
+  if (!synchronizable) {
+    g_warning ("Failed to create synchronizable object from BSO");
+    goto free_bundle;
+  }
+
+  /* Delete the local object and add the remote one if it is not marked as deleted. */
+  ephy_synchronizable_manager_remove (data->manager, data->synchronizable);
+  if (!is_deleted) {
+    ephy_synchronizable_manager_add (data->manager, synchronizable);
+    LOG ("Successfully downloaded from server");
+  }
+
+  g_object_unref (synchronizable);
+free_bundle:
+  ephy_sync_crypto_key_bundle_free (bundle);
+  json_node_unref (node);
+out:
+  sync_async_data_free (data);
+  ephy_sync_service_send_next_storage_request (self);
+}
+
+static void
+ephy_sync_service_download_synchronizable (EphySyncService           *self,
+                                           EphySynchronizableManager *manager,
+                                           EphySynchronizable        *synchronizable)
+{
+  SyncAsyncData *data;
+  char *endpoint;
+  const char *collection;
+  const char *id;
+
+  g_assert (EPHY_IS_SYNC_SERVICE (self));
+  g_assert (EPHY_IS_SYNCHRONIZABLE_MANAGER (manager));
+  g_assert (EPHY_IS_SYNCHRONIZABLE (synchronizable));
+
+  id = ephy_synchronizable_get_id (synchronizable);
+  collection = ephy_synchronizable_manager_get_collection_name (manager);
+  endpoint = g_strdup_printf ("storage/%s/%s", collection, id);
+  data = sync_async_data_new (manager, synchronizable);
+
+  LOG ("Downloading object with id %s...", id);
+  ephy_sync_service_queue_storage_request (self, endpoint,
+                                           SOUP_METHOD_GET, NULL, -1, -1,
+                                           download_synchronizable_cb, data);
+
+  g_free (endpoint);
+}
+
+static void
+upload_synchronizable_cb (SoupSession *session,
+                          SoupMessage *msg,
+                          gpointer     user_data)
+{
+  EphySyncService *self;
+  SyncAsyncData *data;
+  double modified;
+
+  data = (SyncAsyncData *)user_data;
+  self = ephy_shell_get_sync_service (ephy_shell_get_default ());
+
+  /* Code 412 means that there is a more recent version of the object
+   * on the server. Download it. */
+  if (msg->status_code == 412) {
+    LOG ("Found a newer version of the object on the server, downloading it...");
+    ephy_sync_service_download_synchronizable (self, data->manager, data->synchronizable);
+  } else if (msg->status_code == 200) {
+    LOG ("Successfully uploaded to server");
+    modified = g_ascii_strtod (msg->response_body->data, NULL);
+    /* FIXME: Make sure the synchronizable manager commits this change to file/database. */
+    ephy_synchronizable_set_modification_time (data->synchronizable, modified);
+  } else {
+    g_warning ("Failed to upload object. Status code: %u, response: %s",
+               msg->status_code, msg->response_body->data);
+  }
+
+  sync_async_data_free (data);
+  ephy_sync_service_send_next_storage_request (self);
+}
+
+static void
+ephy_sync_service_upload_synchronizable (EphySyncService           *self,
+                                         EphySynchronizableManager *manager,
+                                         EphySynchronizable        *synchronizable)
+{
+  SyncCryptoKeyBundle *bundle;
+  SyncAsyncData *data;
+  JsonNode *bso;
+  char *endpoint;
+  char *body;
+  const char *collection;
+  const char *id;
+
+  g_assert (EPHY_IS_SYNC_SERVICE (self));
+  g_assert (EPHY_IS_SYNCHRONIZABLE_MANAGER (manager));
+  g_assert (EPHY_IS_SYNCHRONIZABLE (synchronizable));
+
+  collection = ephy_synchronizable_manager_get_collection_name (manager);
+  bundle = ephy_sync_service_get_key_bundle (self, collection);
+  bso = ephy_synchronizable_to_bso (synchronizable, bundle);
+  id = ephy_synchronizable_get_id (synchronizable);
+  endpoint = g_strdup_printf ("storage/%s/%s", collection, id);
+  data = sync_async_data_new (manager, synchronizable);
+  body = json_to_string (bso, FALSE);
+
+  LOG ("Uploading object with id %s...", id);
+  ephy_sync_service_queue_storage_request (self, endpoint, SOUP_METHOD_PUT, body, -1,
+                                           ephy_synchronizable_get_modification_time (synchronizable),
+                                           upload_synchronizable_cb, data);
+
+  g_free (body);
+  g_free (endpoint);
+  json_node_unref (bso);
+  ephy_sync_crypto_key_bundle_free (bundle);
+}
+
+static void
+sync_collection_cb (SoupSession *session,
+                    SoupMessage *msg,
+                    gpointer     user_data)
+{
+  EphySyncService *self;
+  SyncCollectionAsyncData *data;
+  EphySynchronizable *remote;
+  SyncCryptoKeyBundle *bundle;
+  JsonNode *node = NULL;
+  JsonArray *array;
+  GError *error = NULL;
+  GList *remotes_updated = NULL;
+  GList *remotes_deleted = NULL;
+  GList *to_upload;
+  GType type;
+  const char *collection;
+  const char *timestamp;
+  gboolean is_deleted;
+
+  self = ephy_shell_get_sync_service (ephy_shell_get_default ());
+  data = (SyncCollectionAsyncData *)user_data;
+  collection = ephy_synchronizable_manager_get_collection_name (data->manager);
+
+  /* Code 304 means that the collection has not been modified. */
+  if (msg->status_code == 304) {
+    LOG ("There are no new remote objects");
+    goto merge_remotes;
+  }
+
+  if (msg->status_code != 200) {
+    g_warning ("Failed to get records in collection %s. Status code: %u, response: %s",
+               collection, msg->status_code, msg->response_body->data);
+    goto out;
+  }
+
+  node = json_from_string (msg->response_body->data, &error);
+  if (error) {
+    g_warning ("Response is not a valid JSON: %s", error->message);
+    g_error_free (error);
+    goto out;
+  }
+  if (!JSON_NODE_HOLDS_ARRAY (node)) {
+    g_warning ("JSON root does not hold an array");
+    goto free_node;
+  }
+
+  type = ephy_synchronizable_manager_get_synchronizable_type (data->manager);
+  bundle = ephy_sync_service_get_key_bundle (self, collection);
+  array = json_node_get_array (node);
+
+  for (guint i = 0; i < json_array_get_length (array); i++) {
+    remote = EPHY_SYNCHRONIZABLE (ephy_synchronizable_from_bso (json_array_get_element (array, i),
+                                                                type, bundle, &is_deleted));
+    if (!remote) {
+      g_warning ("Failed to create synchronizable object from BSO, skipping...");
+      continue;
+    }
+    if (is_deleted)
+      remotes_deleted = g_list_prepend (remotes_deleted, remote);
+    else
+      remotes_updated = g_list_prepend (remotes_updated, remote);
+  }
+
+merge_remotes:
+  to_upload = ephy_synchronizable_manager_merge_remotes (data->manager, data->is_initial,
+                                                         remotes_deleted, remotes_updated);
+
+  if (to_upload) {
+    LOG ("Uploading local objects to server...");
+    for (GList *l = to_upload; l && l->data; l = l->next) {
+      ephy_sync_service_upload_synchronizable (self, data->manager,
+                                               EPHY_SYNCHRONIZABLE (l->data));
+    }
+  }
+
+  ephy_synchronizable_manager_set_is_initial_sync (data->manager, FALSE);
+  /* Update sync time. */
+  timestamp = soup_message_headers_get_one (msg->response_headers, "X-Weave-Timestamp");
+  ephy_synchronizable_manager_set_sync_time (data->manager, g_ascii_strtod (timestamp, NULL));
+
+  g_list_free_full (to_upload, g_object_unref);
+  g_list_free_full (remotes_updated, g_object_unref);
+  g_list_free_full (remotes_deleted, g_object_unref);
+free_node:
+  if (node)
+    json_node_unref (node);
+out:
+  if (data->collection_index == data->num_collections)
+    g_signal_emit (self, signals[SYNC_FINISHED], 0);
+
+  sync_collection_async_data_free (data);
+  ephy_sync_service_send_next_storage_request (self);
+}
+
+static void
+ephy_sync_service_sync_collection (EphySyncService           *self,
+                                   EphySynchronizableManager *manager,
+                                   guint                      collection_index,
+                                   guint                      num_collections)
+{
+  SyncCollectionAsyncData *data;
+  const char *collection;
+  char *endpoint;
+  gboolean is_initial;
+
+  g_assert (EPHY_IS_SYNC_SERVICE (self));
+  g_assert (EPHY_IS_SYNCHRONIZABLE_MANAGER (manager));
+
+  collection = ephy_synchronizable_manager_get_collection_name (manager);
+  endpoint = g_strdup_printf ("storage/%s?full=true", collection);
+  is_initial = ephy_synchronizable_manager_is_initial_sync (manager);
+  data = sync_collection_async_data_new (manager, is_initial, collection_index, num_collections);
+
+  LOG ("Syncing %s collection%s...", collection, is_initial ? " first time" : "");
+  ephy_sync_service_queue_storage_request (self, endpoint, SOUP_METHOD_GET, NULL,
+                                           is_initial ? -1 : ephy_synchronizable_manager_get_sync_time 
(manager),
+                                           -1, sync_collection_cb, data);
+
+  g_free (endpoint);
+}
+
+static gboolean
+ephy_sync_service_sync (gpointer user_data)
+{
+  EphySyncService *self = EPHY_SYNC_SERVICE (user_data);
+  GList *managers = NULL;
+
+  managers = ephy_shell_get_synchronizable_managers (ephy_shell_get_default ());
+  if (managers) {
+    guint num_managers = g_list_length (managers);
+    guint index = 1;
+
+    for (GList *l = managers; l && l->data; l = l->next, index++)
+      ephy_sync_service_sync_collection (self,
+                                         EPHY_SYNCHRONIZABLE_MANAGER (l->data),
+                                         index, num_managers);
+
+    g_list_free (managers);
+  } else {
+    g_signal_emit (self, signals[SYNC_FINISHED], 0);
+  }
+
+  return G_SOURCE_CONTINUE;
+}
+
+static void
+ephy_sync_service_stop_periodical_sync (EphySyncService *self)
+{
+  g_assert (EPHY_IS_SYNC_SERVICE (self));
+
+  if (self->source_id != 0) {
+    g_source_remove (self->source_id);
+    self->source_id = 0;
+  }
+}
+
+static void
+ephy_sync_service_schedule_periodical_sync (EphySyncService *self)
+{
+  g_assert (EPHY_IS_SYNC_SERVICE (self));
+
+  self->source_id = g_timeout_add_seconds (g_settings_get_uint (EPHY_SETTINGS_SYNC,
+                                                                EPHY_PREFS_SYNC_FREQUENCY) * 60,
+                                           ephy_sync_service_sync,
+                                           self);
+  LOG ("Scheduled new sync with frequency %u mins",
+       g_settings_get_uint (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_FREQUENCY));
+}
+
+static void
+sync_frequency_changed_cb (EphySyncService *self)
+{
+  g_assert (EPHY_IS_SYNC_SERVICE (self));
+
+  ephy_sync_service_stop_periodical_sync (self);
+  ephy_sync_service_schedule_periodical_sync (self);
+}
+
+static void
+sync_secrets_store_finished_cb (EphySyncService *self,
+                                GError          *error)
+{
+  g_assert (EPHY_IS_SYNC_SERVICE (self));
+
+  if (error) {
+    ephy_sync_service_destroy_session (self);
+    g_clear_pointer (&self->user_email, g_free);
+    g_hash_table_remove_all (self->secrets);
+  }
+}
+
+static void
 ephy_sync_service_finalize (GObject *object)
 {
   EphySyncService *self = EPHY_SYNC_SERVICE (object);
@@ -988,61 +1382,6 @@ ephy_sync_service_set_secret (EphySyncService *self,
 }
 
 static void
-destroy_session_cb (SoupSession *session,
-                    SoupMessage *msg,
-                    gpointer     user_data)
-{
-  if (msg->status_code != 200)
-    g_warning ("Failed to destroy session. Status code: %u, response: %s",
-               msg->status_code, msg->response_body->data);
-  else
-    LOG ("Successfully destroyed session");
-}
-
-static void
-ephy_sync_service_destroy_session (EphySyncService *self)
-{
-  SyncCryptoHawkOptions *hoptions;
-  SyncCryptoHawkHeader *hheader;
-  SoupMessage *msg;
-  guint8 *tokenID;
-  guint8 *reqHMACkey;
-  guint8 *requestKey;
-  char *tokenID_hex;
-  char *url;
-  const char *content_type = "application/json";
-  const char *request_body = "{}";
-
-  g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
-  g_return_if_fail (ephy_sync_service_get_secret (self, secrets[SESSION_TOKEN]));
-
-  url = g_strdup_printf ("%ssession/destroy", MOZILLA_FXA_SERVER_URL);
-  ephy_sync_crypto_process_session_token (ephy_sync_service_get_secret (self, secrets[SESSION_TOKEN]),
-                                          &tokenID, &reqHMACkey, &requestKey, TOKEN_LENGTH);
-  tokenID_hex = ephy_sync_crypto_encode_hex (tokenID, TOKEN_LENGTH);
-
-  msg = soup_message_new (SOUP_METHOD_POST, url);
-  soup_message_set_request (msg, content_type, SOUP_MEMORY_STATIC,
-                            request_body, strlen (request_body));
-  hoptions = ephy_sync_crypto_hawk_options_new (NULL, NULL, NULL, content_type,
-                                                NULL, NULL, NULL, request_body, NULL);
-  hheader = ephy_sync_crypto_compute_hawk_header (url, "POST", tokenID_hex,
-                                                  reqHMACkey, TOKEN_LENGTH,
-                                                  hoptions);
-  soup_message_headers_append (msg->request_headers, "authorization", hheader->header);
-  soup_message_headers_append (msg->request_headers, "content-type", content_type);
-  soup_session_queue_message (self->session, msg, destroy_session_cb, NULL);
-
-  ephy_sync_crypto_hawk_options_free (hoptions);
-  ephy_sync_crypto_hawk_header_free (hheader);
-  g_free (tokenID_hex);
-  g_free (tokenID);
-  g_free (reqHMACkey);
-  g_free (requestKey);
-  g_free (url);
-}
-
-static void
 ephy_sync_service_report_sign_in_error (EphySyncService *self,
                                         const char      *message,
                                         gboolean         clear_secrets)
@@ -1459,348 +1798,6 @@ ephy_sync_service_delete_synchronizable (EphySyncService           *self,
   g_free (endpoint);
 }
 
-static void
-download_synchronizable_cb (SoupSession *session,
-                            SoupMessage *msg,
-                            gpointer     user_data)
-{
-  EphySyncService *self;
-  EphySynchronizable *synchronizable;
-  SyncCryptoKeyBundle *bundle;
-  SyncAsyncData *data;
-  JsonNode *node;
-  GError *error = NULL;
-  GType type;
-  const char *collection;
-  gboolean is_deleted;
-
-  data = (SyncAsyncData *)user_data;
-  self = ephy_shell_get_sync_service (ephy_shell_get_default ());
-
-  if (msg->status_code != 200) {
-    g_warning ("Failed to download object. Status code: %u, response: %s",
-               msg->status_code, msg->response_body->data);
-    goto out;
-  }
-
-  node = json_from_string (msg->response_body->data, &error);
-  if (error) {
-    g_warning ("Response is not a valid JSON");
-    g_error_free (error);
-    goto out;
-  }
-
-  type = ephy_synchronizable_manager_get_synchronizable_type (data->manager);
-  collection = ephy_synchronizable_manager_get_collection_name (data->manager);
-  bundle = ephy_sync_service_get_key_bundle (self, collection);
-  synchronizable = EPHY_SYNCHRONIZABLE (ephy_synchronizable_from_bso (node, type, bundle, &is_deleted));
-  if (!synchronizable) {
-    g_warning ("Failed to create synchronizable object from BSO");
-    goto free_bundle;
-  }
-
-  /* Delete the local object and add the remote one if it is not marked as deleted. */
-  ephy_synchronizable_manager_remove (data->manager, data->synchronizable);
-  if (!is_deleted) {
-    ephy_synchronizable_manager_add (data->manager, synchronizable);
-    LOG ("Successfully downloaded from server");
-  }
-
-  g_object_unref (synchronizable);
-free_bundle:
-  ephy_sync_crypto_key_bundle_free (bundle);
-  json_node_unref (node);
-out:
-  sync_async_data_free (data);
-  ephy_sync_service_send_next_storage_request (self);
-}
-
-static void
-ephy_sync_service_download_synchronizable (EphySyncService           *self,
-                                           EphySynchronizableManager *manager,
-                                           EphySynchronizable        *synchronizable)
-{
-  SyncAsyncData *data;
-  char *endpoint;
-  const char *collection;
-  const char *id;
-
-  g_assert (EPHY_IS_SYNC_SERVICE (self));
-  g_assert (EPHY_IS_SYNCHRONIZABLE_MANAGER (manager));
-  g_assert (EPHY_IS_SYNCHRONIZABLE (synchronizable));
-
-  id = ephy_synchronizable_get_id (synchronizable);
-  collection = ephy_synchronizable_manager_get_collection_name (manager);
-  endpoint = g_strdup_printf ("storage/%s/%s", collection, id);
-  data = sync_async_data_new (manager, synchronizable);
-
-  LOG ("Downloading object with id %s...", id);
-  ephy_sync_service_queue_storage_request (self, endpoint,
-                                           SOUP_METHOD_GET, NULL, -1, -1,
-                                           download_synchronizable_cb, data);
-
-  g_free (endpoint);
-}
-
-static void
-upload_synchronizable_cb (SoupSession *session,
-                          SoupMessage *msg,
-                          gpointer     user_data)
-{
-  EphySyncService *self;
-  SyncAsyncData *data;
-  double modified;
-
-  data = (SyncAsyncData *)user_data;
-  self = ephy_shell_get_sync_service (ephy_shell_get_default ());
-
-  /* Code 412 means that there is a more recent version of the object
-   * on the server. Download it. */
-  if (msg->status_code == 412) {
-    LOG ("Found a newer version of the object on the server, downloading it...");
-    ephy_sync_service_download_synchronizable (self, data->manager, data->synchronizable);
-  } else if (msg->status_code == 200) {
-    LOG ("Successfully uploaded to server");
-    modified = g_ascii_strtod (msg->response_body->data, NULL);
-    /* FIXME: Make sure the synchronizable manager commits this change to file/database. */
-    ephy_synchronizable_set_modification_time (data->synchronizable, modified);
-  } else {
-    g_warning ("Failed to upload object. Status code: %u, response: %s",
-               msg->status_code, msg->response_body->data);
-  }
-
-  sync_async_data_free (data);
-  ephy_sync_service_send_next_storage_request (self);
-}
-
-static void
-ephy_sync_service_upload_synchronizable (EphySyncService           *self,
-                                         EphySynchronizableManager *manager,
-                                         EphySynchronizable        *synchronizable)
-{
-  SyncCryptoKeyBundle *bundle;
-  SyncAsyncData *data;
-  JsonNode *bso;
-  char *endpoint;
-  char *body;
-  const char *collection;
-  const char *id;
-
-  g_assert (EPHY_IS_SYNC_SERVICE (self));
-  g_assert (EPHY_IS_SYNCHRONIZABLE_MANAGER (manager));
-  g_assert (EPHY_IS_SYNCHRONIZABLE (synchronizable));
-
-  collection = ephy_synchronizable_manager_get_collection_name (manager);
-  bundle = ephy_sync_service_get_key_bundle (self, collection);
-  bso = ephy_synchronizable_to_bso (synchronizable, bundle);
-  id = ephy_synchronizable_get_id (synchronizable);
-  endpoint = g_strdup_printf ("storage/%s/%s", collection, id);
-  data = sync_async_data_new (manager, synchronizable);
-  body = json_to_string (bso, FALSE);
-
-  LOG ("Uploading object with id %s...", id);
-  ephy_sync_service_queue_storage_request (self, endpoint, SOUP_METHOD_PUT, body, -1,
-                                           ephy_synchronizable_get_modification_time (synchronizable),
-                                           upload_synchronizable_cb, data);
-
-  g_free (body);
-  g_free (endpoint);
-  json_node_unref (bso);
-  ephy_sync_crypto_key_bundle_free (bundle);
-}
-
-static void
-sync_collection_cb (SoupSession *session,
-                    SoupMessage *msg,
-                    gpointer     user_data)
-{
-  EphySyncService *self;
-  SyncCollectionAsyncData *data;
-  EphySynchronizable *remote;
-  SyncCryptoKeyBundle *bundle;
-  JsonNode *node = NULL;
-  JsonArray *array;
-  GError *error = NULL;
-  GList *remotes_updated = NULL;
-  GList *remotes_deleted = NULL;
-  GList *to_upload;
-  GType type;
-  const char *collection;
-  const char *timestamp;
-  gboolean is_deleted;
-
-  self = ephy_shell_get_sync_service (ephy_shell_get_default ());
-  data = (SyncCollectionAsyncData *)user_data;
-  collection = ephy_synchronizable_manager_get_collection_name (data->manager);
-
-  /* Code 304 means that the collection has not been modified. */
-  if (msg->status_code == 304) {
-    LOG ("There are no new remote objects");
-    goto merge_remotes;
-  }
-
-  if (msg->status_code != 200) {
-    g_warning ("Failed to get records in collection %s. Status code: %u, response: %s",
-               collection, msg->status_code, msg->response_body->data);
-    goto out;
-  }
-
-  node = json_from_string (msg->response_body->data, &error);
-  if (error) {
-    g_warning ("Response is not a valid JSON: %s", error->message);
-    g_error_free (error);
-    goto out;
-  }
-  if (!JSON_NODE_HOLDS_ARRAY (node)) {
-    g_warning ("JSON root does not hold an array");
-    goto free_node;
-  }
-
-  type = ephy_synchronizable_manager_get_synchronizable_type (data->manager);
-  bundle = ephy_sync_service_get_key_bundle (self, collection);
-  array = json_node_get_array (node);
-
-  for (guint i = 0; i < json_array_get_length (array); i++) {
-    remote = EPHY_SYNCHRONIZABLE (ephy_synchronizable_from_bso (json_array_get_element (array, i),
-                                                                type, bundle, &is_deleted));
-    if (!remote) {
-      g_warning ("Failed to create synchronizable object from BSO, skipping...");
-      continue;
-    }
-    if (is_deleted)
-      remotes_deleted = g_list_prepend (remotes_deleted, remote);
-    else
-      remotes_updated = g_list_prepend (remotes_updated, remote);
-  }
-
-merge_remotes:
-  to_upload = ephy_synchronizable_manager_merge_remotes (data->manager, data->is_initial,
-                                                         remotes_deleted, remotes_updated);
-
-  if (to_upload) {
-    LOG ("Uploading local objects to server...");
-    for (GList *l = to_upload; l && l->data; l = l->next) {
-      ephy_sync_service_upload_synchronizable (self, data->manager,
-                                               EPHY_SYNCHRONIZABLE (l->data));
-    }
-  }
-
-  ephy_synchronizable_manager_set_is_initial_sync (data->manager, FALSE);
-  /* Update sync time. */
-  timestamp = soup_message_headers_get_one (msg->response_headers, "X-Weave-Timestamp");
-  ephy_synchronizable_manager_set_sync_time (data->manager, g_ascii_strtod (timestamp, NULL));
-
-  g_list_free_full (to_upload, g_object_unref);
-  g_list_free_full (remotes_updated, g_object_unref);
-  g_list_free_full (remotes_deleted, g_object_unref);
-free_node:
-  if (node)
-    json_node_unref (node);
-out:
-  if (data->collection_index == data->num_collections)
-    g_signal_emit (self, signals[SYNC_FINISHED], 0);
-
-  sync_collection_async_data_free (data);
-  ephy_sync_service_send_next_storage_request (self);
-}
-
-static void
-ephy_sync_service_sync_collection (EphySyncService           *self,
-                                   EphySynchronizableManager *manager,
-                                   guint                      collection_index,
-                                   guint                      num_collections)
-{
-  SyncCollectionAsyncData *data;
-  const char *collection;
-  char *endpoint;
-  gboolean is_initial;
-
-  g_assert (EPHY_IS_SYNC_SERVICE (self));
-  g_assert (EPHY_IS_SYNCHRONIZABLE_MANAGER (manager));
-
-  collection = ephy_synchronizable_manager_get_collection_name (manager);
-  endpoint = g_strdup_printf ("storage/%s?full=true", collection);
-  is_initial = ephy_synchronizable_manager_is_initial_sync (manager);
-  data = sync_collection_async_data_new (manager, is_initial, collection_index, num_collections);
-
-  LOG ("Syncing %s collection%s...", collection, is_initial ? " first time" : "");
-  ephy_sync_service_queue_storage_request (self, endpoint, SOUP_METHOD_GET, NULL,
-                                           is_initial ? -1 : ephy_synchronizable_manager_get_sync_time 
(manager),
-                                           -1, sync_collection_cb, data);
-
-  g_free (endpoint);
-}
-
-static void
-ephy_sync_service_stop_periodical_sync (EphySyncService *self)
-{
-  g_assert (EPHY_IS_SYNC_SERVICE (self));
-
-  if (self->source_id != 0) {
-    g_source_remove (self->source_id);
-    self->source_id = 0;
-  }
-}
-
-static gboolean
-ephy_sync_service_sync (gpointer user_data)
-{
-  EphySyncService *self = EPHY_SYNC_SERVICE (user_data);
-  GList *managers = NULL;
-
-  managers = ephy_shell_get_synchronizable_managers (ephy_shell_get_default ());
-  if (managers) {
-    guint num_managers = g_list_length (managers);
-    guint index = 1;
-
-    for (GList *l = managers; l && l->data; l = l->next, index++)
-      ephy_sync_service_sync_collection (self,
-                                         EPHY_SYNCHRONIZABLE_MANAGER (l->data),
-                                         index, num_managers);
-
-    g_list_free (managers);
-  } else {
-    g_signal_emit (self, signals[SYNC_FINISHED], 0);
-  }
-
-  return G_SOURCE_CONTINUE;
-}
-
-static void
-ephy_sync_service_schedule_periodical_sync (EphySyncService *self)
-{
-  g_assert (EPHY_IS_SYNC_SERVICE (self));
-
-  self->source_id = g_timeout_add_seconds (g_settings_get_uint (EPHY_SETTINGS_SYNC,
-                                                                EPHY_PREFS_SYNC_FREQUENCY) * 60,
-                                           ephy_sync_service_sync,
-                                           self);
-  LOG ("Scheduled new sync with frequency %u mins",
-       g_settings_get_uint (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_FREQUENCY));
-}
-
-static void
-sync_frequency_changed_cb (EphySyncService *self)
-{
-  g_assert (EPHY_IS_SYNC_SERVICE (self));
-
-  ephy_sync_service_stop_periodical_sync (self);
-  ephy_sync_service_schedule_periodical_sync (self);
-}
-
-static void
-sync_secrets_store_finished_cb (EphySyncService *self,
-                                GError          *error)
-{
-  g_assert (EPHY_IS_SYNC_SERVICE (self));
-
-  if (error) {
-    ephy_sync_service_destroy_session (self);
-    g_clear_pointer (&self->user_email, g_free);
-    g_hash_table_remove_all (self->secrets);
-  }
-}
-
 void
 ephy_sync_service_do_sync (EphySyncService *self)
 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]