[epiphany/wip/sync: 12/19] sync: Change the way sync tokens are handled



commit 5870689cd2930288cc14f2b4238852f17af141f4
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Wed Apr 12 16:19:17 2017 +0300

    sync: Change the way sync tokens are handled

 src/ephy-shell.c             |   12 +-
 src/prefs-dialog.c           |   17 +---
 src/sync/ephy-sync-secret.c  |  112 +++++++++++-----------
 src/sync/ephy-sync-secret.h  |   10 +-
 src/sync/ephy-sync-service.c |  219 +++++++++++++++++-------------------------
 src/sync/ephy-sync-service.h |   55 ++++-------
 6 files changed, 182 insertions(+), 243 deletions(-)
---
diff --git a/src/ephy-shell.c b/src/ephy-shell.c
index 0a91cc9..520840a 100644
--- a/src/ephy-shell.c
+++ b/src/ephy-shell.c
@@ -308,15 +308,15 @@ download_started_cb (WebKitWebContext *web_context,
 }
 
 static void
-sync_tokens_load_finished_cb (EphySyncService *service,
-                              GError          *error,
-                              gpointer         user_data)
+sync_secrets_load_finished_cb (EphySyncService *service,
+                               GError          *error,
+                               gpointer         user_data)
 {
   EphyNotification *notification;
 
   g_assert (EPHY_IS_SYNC_SERVICE (service));
 
-  /* If the tokens were successfully loaded, start the periodical sync.
+  /* If the sync secrets were successfully loaded, start the periodical sync.
    * Otherwise, notify the user to sign in again. */
   if (error == NULL) {
     ephy_sync_service_start_periodical_sync (service);
@@ -369,8 +369,8 @@ ephy_shell_startup (GApplication *application)
     /* Create the sync service. */
     ephy_shell->sync_service = ephy_sync_service_new ();
     g_signal_connect (ephy_shell->sync_service,
-                      "sync-tokens-load-finished",
-                      G_CALLBACK (sync_tokens_load_finished_cb), NULL);
+                      "sync-secrets-load-finished",
+                      G_CALLBACK (sync_secrets_load_finished_cb), NULL);
 
     gtk_application_set_app_menu (GTK_APPLICATION (application),
                                   G_MENU_MODEL (gtk_builder_get_object (builder, "app-menu")));
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index 5db7b55..d04da26 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -209,9 +209,9 @@ sync_sign_in_error_cb (EphySyncService *service,
 }
 
 static void
-sync_tokens_store_finished_cb (EphySyncService *service,
-                               GError          *error,
-                               PrefsDialog     *dialog)
+sync_secrets_store_finished_cb (EphySyncService *service,
+                                GError          *error,
+                                PrefsDialog     *dialog)
 {
   g_assert (EPHY_IS_SYNC_SERVICE (service));
   g_assert (EPHY_IS_PREFS_DIALOG (dialog));
@@ -244,13 +244,6 @@ sync_tokens_store_finished_cb (EphySyncService *service,
     g_free (text);
     g_free (account);
   } else {
-    /* Destroy the current session. */
-    ephy_sync_service_destroy_session (service);
-
-    /* Unset the email and tokens. */
-    ephy_sync_service_set_user_email (service, NULL);
-    ephy_sync_service_clear_tokens (service);
-
     /* Display the error message and reload the iframe. */
     sync_sign_in_details_show (dialog, error->message);
     webkit_web_view_load_uri (dialog->fxa_web_view, FXA_IFRAME_URL);
@@ -1631,8 +1624,8 @@ setup_sync_page (PrefsDialog *dialog)
     g_free (account);
   }
 
-  g_signal_connect_object (dialog->sync_service, "sync-tokens-store-finished",
-                           G_CALLBACK (sync_tokens_store_finished_cb),
+  g_signal_connect_object (dialog->sync_service, "sync-secrets-store-finished",
+                           G_CALLBACK (sync_secrets_store_finished_cb),
                            dialog, 0);
   g_signal_connect_object (dialog->sync_service, "sync-sign-in-error",
                            G_CALLBACK (sync_sign_in_error_cb),
diff --git a/src/sync/ephy-sync-secret.c b/src/sync/ephy-sync-secret.c
index affb253..7663889 100644
--- a/src/sync/ephy-sync-secret.c
+++ b/src/sync/ephy-sync-secret.c
@@ -33,10 +33,10 @@ enum {
 };
 
 const SecretSchema *
-ephy_sync_secret_get_token_schema (void)
+ephy_sync_secret_get_secret_schema (void)
 {
   static const SecretSchema schema = {
-    "org.epiphany.SyncTokens", SECRET_SCHEMA_NONE,
+    "org.epiphany.SyncSecrets", SECRET_SCHEMA_NONE,
     {
       { EMAIL_KEY, SECRET_SCHEMA_ATTRIBUTE_STRING },
       { "NULL", 0 },
@@ -47,9 +47,9 @@ ephy_sync_secret_get_token_schema (void)
 }
 
 static void
-forget_tokens_cb (SecretService *service,
-                  GAsyncResult  *result,
-                  gpointer       user_data)
+forget_secrets_cb (SecretService *service,
+                   GAsyncResult  *result,
+                   gpointer       user_data)
 {
   GError *error = NULL;
 
@@ -62,21 +62,21 @@ forget_tokens_cb (SecretService *service,
 }
 
 void
-ephy_sync_secret_forget_tokens (void)
+ephy_sync_secret_forget_secrets (void)
 {
   GHashTable *attributes;
 
-  attributes = secret_attributes_build (EPHY_SYNC_TOKEN_SCHEMA, NULL);
-  secret_service_clear (NULL, EPHY_SYNC_TOKEN_SCHEMA, attributes,
-                        NULL, (GAsyncReadyCallback)forget_tokens_cb, NULL);
+  attributes = secret_attributes_build (EPHY_SYNC_SECRET_SCHEMA, NULL);
+  secret_service_clear (NULL, EPHY_SYNC_SECRET_SCHEMA, attributes,
+                        NULL, (GAsyncReadyCallback)forget_secrets_cb, NULL);
 
   g_hash_table_unref (attributes);
 }
 
 static void
-load_tokens_cb (SecretService *service,
-                GAsyncResult  *result,
-                gpointer       user_data)
+load_secrets_cb (SecretService *service,
+                 GAsyncResult  *result,
+                 gpointer       user_data)
 {
   EphySyncService *sync_service = EPHY_SYNC_SERVICE (user_data);
   SecretItem *item;
@@ -97,9 +97,9 @@ load_tokens_cb (SecretService *service,
     g_set_error (&ret_error,
                  SYNC_SECRET_ERROR,
                  SYNC_SECRET_ERROR_LOAD,
-                 _("The sync tokens could not be found."));
+                 _("The sync secrets could not be found."));
     if (error)
-      g_warning ("sync-secret: Failed to find the tokens: %s", error->message);
+      g_warning ("sync-secret: Failed to find sync secrets: %s", error->message);
     goto out;
   }
 
@@ -107,7 +107,7 @@ load_tokens_cb (SecretService *service,
     g_set_error (&ret_error,
                  SYNC_SECRET_ERROR,
                  SYNC_SECRET_ERROR_LOAD,
-                 _("Found more than one set of sync tokens."));
+                 _("Found more than one set of sync secrets."));
     g_warning ("sync-secret: Was expecting exactly one match, found more.");
     goto out;
   }
@@ -121,7 +121,7 @@ load_tokens_cb (SecretService *service,
     g_set_error (&ret_error,
                  SYNC_SECRET_ERROR,
                  SYNC_SECRET_ERROR_LOAD,
-                 _("Could not find the sync tokens for the currently logged-in user."));
+                 _("Could not find the sync secrets for the currently logged-in user."));
     g_warning ("sync-secret: Emails differ: %s vs %s", email, user_email);
     goto out;
   }
@@ -131,8 +131,8 @@ load_tokens_cb (SecretService *service,
     g_set_error (&ret_error,
                  SYNC_SECRET_ERROR,
                  SYNC_SECRET_ERROR_LOAD,
-                 _("Could not get the secret value of the sync tokens."));
-    g_warning ("sync-secret: The secret item of the tokens has a NULL value.");
+                 _("Could not get the secret value of the sync secrets."));
+    g_warning ("sync-secret: The secret item of the secrets has a NULL value.");
     goto out;
   }
 
@@ -141,7 +141,7 @@ load_tokens_cb (SecretService *service,
     g_set_error (&ret_error,
                  SYNC_SECRET_ERROR,
                  SYNC_SECRET_ERROR_LOAD,
-                 _("The sync tokens are not a valid JSON."));
+                 _("The sync secrets are not a valid JSON."));
     g_warning ("sync-secret: Failed to load JSON from data: %s", error->message);
     goto out;
   }
@@ -149,16 +149,16 @@ load_tokens_cb (SecretService *service,
   json = json_node_get_object (node);
   members = json_object_get_members (json);
 
-  /* Set the tokens. */
   for (GList *m = members; m != NULL; m = m->next) {
-    ephy_sync_service_set_token (sync_service,
-                                 json_object_get_string_member (json, m->data),
-                                 ephy_sync_service_token_type_from_name (m->data));
+    ephy_sync_service_set_secret (sync_service,
+                                  (const char *)m->data,
+                                  json_object_get_string_member (json,
+                                                                 (const char *)m->data));
   }
 
 out:
-  /* Notify whether the tokens were successfully loaded. */
-  g_signal_emit_by_name (sync_service, "sync-tokens-load-finished", ret_error);
+  /* Notify whether the secrets were successfully loaded. */
+  g_signal_emit_by_name (sync_service, "sync-secrets-load-finished", ret_error);
 
   if (error)
     g_error_free (error);
@@ -173,20 +173,20 @@ out:
 }
 
 void
-ephy_sync_secret_load_tokens (EphySyncService *service)
+ephy_sync_secret_load_secrets (EphySyncService *service)
 {
   GHashTable *attributes;
 
-  attributes = secret_attributes_build (EPHY_SYNC_TOKEN_SCHEMA, NULL);
-  secret_service_search (NULL, EPHY_SYNC_TOKEN_SCHEMA, attributes,
+  attributes = secret_attributes_build (EPHY_SYNC_SECRET_SCHEMA, NULL);
+  secret_service_search (NULL, EPHY_SYNC_SECRET_SCHEMA, attributes,
                          SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS,
-                         NULL, (GAsyncReadyCallback)load_tokens_cb, service);
+                         NULL, (GAsyncReadyCallback)load_secrets_cb, service);
 
   g_hash_table_unref (attributes);
 }
 
 static void
-store_tokens_cb (SecretService *service,
+store_secrets_cb (SecretService *service,
                  GAsyncResult  *result,
                  gpointer       user_data)
 {
@@ -195,55 +195,55 @@ store_tokens_cb (SecretService *service,
 
   secret_service_store_finish (service, result, &error);
 
-  /* Notify whether the tokens were successfully stored. */
-  g_signal_emit_by_name (sync_service, "sync-tokens-store-finished", error);
+  /* Notify whether the secrets were successfully stored. */
+  g_signal_emit_by_name (sync_service, "sync-secrets-store-finished", error);
 
   if (error)
     g_error_free (error);
 }
 
 void
-ephy_sync_secret_store_tokens (EphySyncService *service)
+ephy_sync_secret_store_secrets (EphySyncService *service)
 {
   JsonNode *node;
   JsonObject *object;
-  SecretValue *value;
+  SecretValue *secret_value;
   GHashTable *attributes;
-  char *tokens;
+  GHashTable *secrets;
+  GHashTableIter iter;
+  gpointer key;
+  gpointer value;
+  char *to_store;
   char *label;
 
+  g_return_if_fail (EPHY_IS_SYNC_SERVICE (service));
+
   node = json_node_new (JSON_NODE_OBJECT);
   object = json_object_new ();
-  json_object_set_string_member (object,
-                                 ephy_sync_service_token_name_from_type (TOKEN_UID),
-                                 ephy_sync_service_get_token (service, TOKEN_UID));
-  json_object_set_string_member (object,
-                                 ephy_sync_service_token_name_from_type (TOKEN_SESSIONTOKEN),
-                                 ephy_sync_service_get_token (service, TOKEN_SESSIONTOKEN));
-  json_object_set_string_member (object,
-                                 ephy_sync_service_token_name_from_type (TOKEN_KB),
-                                 ephy_sync_service_get_token (service, TOKEN_KB));
-  json_object_set_string_member (object,
-                                 ephy_sync_service_token_name_from_type (TOKEN_CRYPTOKEYS),
-                                 ephy_sync_service_get_token (service, TOKEN_CRYPTOKEYS));
+
+  secrets = ephy_sync_service_get_secrets (service);
+  g_hash_table_iter_init (&iter, secrets);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    json_object_set_string_member (object, (const char *)key, (const char *)value);
+
   json_node_set_object (node, object);
-  tokens = json_to_string (node, FALSE);
-  value = secret_value_new (tokens, -1, "text/plain");
-  attributes = secret_attributes_build (EPHY_SYNC_TOKEN_SCHEMA, EMAIL_KEY,
+  to_store = json_to_string (node, FALSE);
+  secret_value = secret_value_new (to_store, -1, "text/plain");
+  attributes = secret_attributes_build (EPHY_SYNC_SECRET_SCHEMA, EMAIL_KEY,
                                         ephy_sync_service_get_user_email (service),
                                         NULL);
   /* Translators: The %s represents the email of the user. */
-  label = g_strdup_printf (_("The sync tokens of %s"),
+  label = g_strdup_printf (_("The sync secrets of %s"),
                            ephy_sync_service_get_user_email (service));
 
-  secret_service_store (NULL, EPHY_SYNC_TOKEN_SCHEMA, attributes,
-                        NULL, label, value, NULL,
-                        (GAsyncReadyCallback)store_tokens_cb, service);
+  secret_service_store (NULL, EPHY_SYNC_SECRET_SCHEMA, attributes,
+                        NULL, label, secret_value, NULL,
+                        (GAsyncReadyCallback)store_secrets_cb, service);
 
   g_free (label);
   g_hash_table_unref (attributes);
-  secret_value_unref (value);
-  g_free (tokens);
+  secret_value_unref (secret_value);
+  g_free (to_store);
   json_object_unref (object);
   json_node_unref (node);
 }
diff --git a/src/sync/ephy-sync-secret.h b/src/sync/ephy-sync-secret.h
index ee27ccc..ea168fb 100644
--- a/src/sync/ephy-sync-secret.h
+++ b/src/sync/ephy-sync-secret.h
@@ -27,14 +27,14 @@
 
 G_BEGIN_DECLS
 
-const SecretSchema *ephy_sync_secret_get_token_schema (void) G_GNUC_CONST;
+const SecretSchema *ephy_sync_secret_get_secret_schema (void) G_GNUC_CONST;
 
 #define EMAIL_KEY "email_utf8"
 
-#define EPHY_SYNC_TOKEN_SCHEMA (ephy_sync_secret_get_token_schema ())
+#define EPHY_SYNC_SECRET_SCHEMA (ephy_sync_secret_get_secret_schema ())
 
-void  ephy_sync_secret_forget_tokens  (void);
-void  ephy_sync_secret_load_tokens    (EphySyncService *service);
-void  ephy_sync_secret_store_tokens   (EphySyncService *service);
+void ephy_sync_secret_forget_secrets (void);
+void ephy_sync_secret_load_secrets   (EphySyncService *service);
+void ephy_sync_secret_store_secrets  (EphySyncService *service);
 
 G_END_DECLS
diff --git a/src/sync/ephy-sync-service.c b/src/sync/ephy-sync-service.c
index cb5e8a6..c9ca049 100644
--- a/src/sync/ephy-sync-service.c
+++ b/src/sync/ephy-sync-service.c
@@ -46,10 +46,7 @@ struct _EphySyncService {
   SoupSession *session;
   guint        source_id;
 
-  char        *uid;
-  char        *sessionToken;
-  char        *kB;
-  char        *crypto_keys;
+  GHashTable  *secrets;
 
   char        *user_email;
   double       sync_time;
@@ -68,6 +65,21 @@ struct _EphySyncService {
 G_DEFINE_TYPE (EphySyncService, ephy_sync_service, G_TYPE_OBJECT);
 
 enum {
+  UID,
+  SESSION_TOKEN,
+  MASTER_KEY,
+  CRYPTO_KEYS,
+  LAST_SECRET
+};
+
+static const char * const secrets[LAST_SECRET] = {
+  "uid",
+  "session_token",
+  "master_key",
+  "crypto_keys"
+};
+
+enum {
   STORE_FINISHED,
   LOAD_FINISHED,
   SIGN_IN_ERROR,
@@ -114,6 +126,7 @@ typedef struct {
 static void ephy_sync_service_send_next_storage_request (EphySyncService *self);
 static void ephy_sync_service_stop_periodical_sync (EphySyncService *self);
 static void ephy_sync_service_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,
@@ -253,12 +266,13 @@ ephy_sync_service_get_key_bundle (EphySyncService *self,
   JsonObject *collections;
   JsonArray *array;
   GError *error = NULL;
+  const char *crypto_keys;
 
   g_return_val_if_fail (EPHY_IS_SYNC_SERVICE (self), NULL);
   g_return_val_if_fail (collection, NULL);
-  g_return_val_if_fail (self->crypto_keys, NULL);
 
-  node = json_from_string (self->crypto_keys, &error);
+  crypto_keys = ephy_sync_service_get_secret (self, secrets[CRYPTO_KEYS]);
+  node = json_from_string (crypto_keys, &error);
   g_assert (!error);
   json = json_node_get_object (node);
   collections = json_object_get_object_member (json, "collections");
@@ -272,6 +286,18 @@ ephy_sync_service_get_key_bundle (EphySyncService *self,
   return bundle;
 }
 
+static void
+ephy_sync_service_clear_storage_credentials (EphySyncService *self)
+{
+  g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+
+  g_clear_pointer (&self->certificate, g_free);
+  g_clear_pointer (&self->storage_endpoint, g_free);
+  g_clear_pointer (&self->storage_credentials_id, g_free);
+  g_clear_pointer (&self->storage_credentials_key, g_free);
+  self->storage_credentials_expiry_time = 0;
+}
+
 static gboolean
 ephy_sync_service_storage_credentials_is_expired (EphySyncService *self)
 {
@@ -426,7 +452,7 @@ ephy_sync_service_certificate_is_valid (EphySyncService *self,
   }
   email = json_object_get_string_member (principal, "email");
   expected = g_strdup_printf ("%s@%s",
-                              ephy_sync_service_get_token (self, TOKEN_UID),
+                              ephy_sync_service_get_secret (self, secrets[UID]),
                               soup_uri_get_host (uri));
   if (g_strcmp0 (email, expected)) {
     g_warning ("Expected email %s, found %s", expected, email);
@@ -548,7 +574,7 @@ ephy_sync_service_obtain_storage_credentials (EphySyncService *self)
   audience = get_audience (MOZILLA_TOKEN_SERVER_URL);
   assertion = ephy_sync_crypto_create_assertion (self->certificate, audience,
                                                  ASSERTION_DURATION, self->keypair);
-  kB = ephy_sync_crypto_decode_hex (ephy_sync_service_get_token (self, TOKEN_KB));
+  kB = ephy_sync_crypto_decode_hex (ephy_sync_service_get_secret (self, secrets[MASTER_KEY]));
   hashed_kB = g_compute_checksum_for_data (G_CHECKSUM_SHA256, kB, TOKEN_LENGTH);
   client_state = g_strndup (hashed_kB, TOKEN_LENGTH);
   authorization = g_strdup_printf ("BrowserID %s", assertion);
@@ -672,7 +698,7 @@ ephy_sync_service_obtain_signed_certificate (EphySyncService *self)
   self->keypair = ephy_sync_crypto_generate_rsa_key_pair ();
 
   /* Derive tokenID, reqHMACkey and requestKey from the sessionToken. */
-  ephy_sync_crypto_process_session_token (ephy_sync_service_get_token (self, TOKEN_SESSIONTOKEN),
+  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);
 
@@ -811,6 +837,7 @@ ephy_sync_service_finalize (GObject *object)
     ephy_sync_crypto_rsa_key_pair_free (self->keypair);
 
   g_queue_free_full (self->storage_queue, (GDestroyNotify) storage_request_async_data_free);
+  g_hash_table_destroy (self->secrets);
 
   G_OBJECT_CLASS (ephy_sync_service_parent_class)->finalize (object);
 }
@@ -824,7 +851,6 @@ ephy_sync_service_dispose (GObject *object)
     ephy_sync_service_stop_periodical_sync (self);
 
   ephy_sync_service_clear_storage_credentials (self);
-  ephy_sync_service_clear_tokens (self);
   g_clear_pointer (&self->user_email, g_free);
   g_clear_object (&self->session);
 
@@ -840,7 +866,7 @@ ephy_sync_service_class_init (EphySyncServiceClass *klass)
   object_class->dispose = ephy_sync_service_dispose;
 
   signals[STORE_FINISHED] =
-    g_signal_new ("sync-tokens-store-finished",
+    g_signal_new ("sync-secrets-store-finished",
                   EPHY_TYPE_SYNC_SERVICE,
                   G_SIGNAL_RUN_LAST,
                   0, NULL, NULL, NULL,
@@ -848,7 +874,7 @@ ephy_sync_service_class_init (EphySyncServiceClass *klass)
                   G_TYPE_ERROR);
 
   signals[LOAD_FINISHED] =
-    g_signal_new ("sync-tokens-load-finished",
+    g_signal_new ("sync-secrets-load-finished",
                   EPHY_TYPE_SYNC_SERVICE,
                   G_SIGNAL_RUN_LAST,
                   0, NULL, NULL, NULL,
@@ -887,6 +913,7 @@ ephy_sync_service_init (EphySyncService *self)
 
   self->session = soup_session_new ();
   self->storage_queue = g_queue_new ();
+  self->secrets = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
 
   settings = ephy_embed_prefs_get_settings ();
   user_agent = webkit_settings_get_user_agent (settings);
@@ -895,10 +922,13 @@ ephy_sync_service_init (EphySyncService *self)
   email = g_settings_get_string (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_USER);
 
   if (g_strcmp0 (email, "")) {
-    ephy_sync_service_set_user_email (self, email);
-    ephy_sync_secret_load_tokens (self);
+    self->user_email = g_strdup (email);
+    ephy_sync_secret_load_secrets (self);
   }
 
+  g_signal_connect (self, "sync-secrets-store-finished",
+                    G_CALLBACK (sync_secrets_store_finished_cb),
+                    NULL);
   g_signal_connect (self, "sync-frequency-changed",
                     G_CALLBACK (ephy_sync_service_sync_frequency_changed_cb),
                     NULL);
@@ -928,118 +958,35 @@ ephy_sync_service_get_user_email (EphySyncService *self)
   return self->user_email;
 }
 
-void
-ephy_sync_service_set_user_email (EphySyncService *self,
-                                  const char      *email)
-{
-  g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
-
-  g_free (self->user_email);
-  self->user_email = g_strdup (email);
-}
-
-const char *
-ephy_sync_service_get_token (EphySyncService   *self,
-                             EphySyncTokenType  type)
+GHashTable *
+ephy_sync_service_get_secrets (EphySyncService *self)
 {
   g_return_val_if_fail (EPHY_IS_SYNC_SERVICE (self), NULL);
 
-  switch (type) {
-    case TOKEN_UID:
-      return self->uid;
-    case TOKEN_SESSIONTOKEN:
-      return self->sessionToken;
-    case TOKEN_KB:
-      return self->kB;
-    case TOKEN_CRYPTOKEYS:
-      return self->crypto_keys;
-    default:
-      g_assert_not_reached ();
-  }
+  return self->secrets;
 }
 
-void
-ephy_sync_service_set_token (EphySyncService   *self,
-                             const char        *value,
-                             EphySyncTokenType  type)
-{
-  g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
-  g_return_if_fail (value);
-
-  switch (type) {
-    case TOKEN_UID:
-      g_free (self->uid);
-      self->uid = g_strdup (value);
-      break;
-    case TOKEN_SESSIONTOKEN:
-      g_free (self->sessionToken);
-      self->sessionToken = g_strdup (value);
-      break;
-    case TOKEN_KB:
-      g_free (self->kB);
-      self->kB = g_strdup (value);
-      break;
-    case TOKEN_CRYPTOKEYS:
-      g_free (self->crypto_keys);
-      self->crypto_keys = g_strdup (value);
-      break;
-    default:
-      g_assert_not_reached ();
-  }
-}
 
 const char *
-ephy_sync_service_token_name_from_type (EphySyncTokenType type)
-{
-  switch (type) {
-    case TOKEN_UID:
-      return "uid";
-    case TOKEN_SESSIONTOKEN:
-      return "sessionToken";
-    case TOKEN_KB:
-      return "kB";
-    case TOKEN_CRYPTOKEYS:
-      return "cryptoKeys";
-    default:
-      g_assert_not_reached ();
-  }
-}
-
-EphySyncTokenType
-ephy_sync_service_token_type_from_name (const char *name)
+ephy_sync_service_get_secret (EphySyncService *self,
+                              const char      *name)
 {
-  if (!g_strcmp0 (name, "uid"))
-    return TOKEN_UID;
-  if (!g_strcmp0 (name, "sessionToken"))
-    return TOKEN_SESSIONTOKEN;
-  if (!g_strcmp0 (name, "kB"))
-    return TOKEN_KB;
-  if (!g_strcmp0 (name, "cryptoKeys"))
-    return TOKEN_CRYPTOKEYS;
-  g_assert_not_reached ();
-}
-
-void
-ephy_sync_service_clear_storage_credentials (EphySyncService *self)
-{
-  g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+  g_return_val_if_fail (EPHY_IS_SYNC_SERVICE (self), NULL);
+  g_return_val_if_fail (name, NULL);
 
-  g_clear_pointer (&self->certificate, g_free);
-  g_clear_pointer (&self->storage_endpoint, g_free);
-  g_clear_pointer (&self->storage_credentials_id, g_free);
-  g_clear_pointer (&self->storage_credentials_key, g_free);
-  self->storage_credentials_expiry_time = 0;
+  return g_hash_table_lookup (self->secrets, name);
 }
 
 void
-ephy_sync_service_clear_tokens (EphySyncService *self)
+ephy_sync_service_set_secret (EphySyncService *self,
+                              const char      *name,
+                              const char      *value)
 {
   g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+  g_return_if_fail (name);
+  g_return_if_fail (value);
 
-  g_clear_pointer (&self->uid, g_free);
-  g_clear_pointer (&self->sessionToken, g_free);
-  g_clear_pointer (&self->kB, g_free);
-  g_clear_pointer (&self->crypto_keys, g_free);
+  g_hash_table_replace (self->secrets, g_strdup (name), g_strdup (value));
 }
 
 static void
@@ -1054,7 +1001,7 @@ destroy_session_cb (SoupSession *session,
     LOG ("Successfully destroyed session");
 }
 
-void
+static void
 ephy_sync_service_destroy_session (EphySyncService *self)
 {
   SyncCryptoHawkOptions *hoptions;
@@ -1069,10 +1016,10 @@ ephy_sync_service_destroy_session (EphySyncService *self)
   const char *request_body = "{}";
 
   g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
-  g_return_if_fail (ephy_sync_service_get_token (self, TOKEN_SESSIONTOKEN));
+  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_token (self, TOKEN_SESSIONTOKEN),
+  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);
 
@@ -1100,7 +1047,7 @@ ephy_sync_service_destroy_session (EphySyncService *self)
 static void
 ephy_sync_service_report_sign_in_error (EphySyncService *self,
                                         const char      *message,
-                                        gboolean         clear_tokens)
+                                        gboolean         clear_secrets)
 {
   g_assert (EPHY_IS_SYNC_SERVICE (self));
   g_assert (message);
@@ -1108,9 +1055,9 @@ ephy_sync_service_report_sign_in_error (EphySyncService *self,
   g_signal_emit (self, signals[SIGN_IN_ERROR], 0, message);
   ephy_sync_service_destroy_session (self);
 
-  if (clear_tokens) {
-    ephy_sync_service_set_user_email (self, NULL);
-    ephy_sync_service_clear_tokens (self);
+  if (clear_secrets) {
+    g_clear_pointer (&self->user_email, g_free);
+    g_hash_table_remove_all (self->secrets);
   }
 }
 
@@ -1162,7 +1109,7 @@ obtain_crypto_keys_cb (SoupSession *session,
   /* Derive the Sync Key bundle from kB. The bundle consists of two 32 bytes keys:
    * the first one used as a symmetric encryption key (AES) and the second one
    * used as a HMAC key. */
-  kB = ephy_sync_crypto_decode_hex (ephy_sync_service_get_token (self, TOKEN_KB));
+  kB = ephy_sync_crypto_decode_hex (ephy_sync_service_get_secret (self, secrets[MASTER_KEY]));
   bundle = ephy_sync_crypto_derive_key_bundle (kB, TOKEN_LENGTH);
   payload = json_object_get_string_member (json, "payload");
   crypto_keys = ephy_sync_crypto_decrypt_record (payload, bundle);
@@ -1171,9 +1118,9 @@ obtain_crypto_keys_cb (SoupSession *session,
     goto free_bundle;
   }
 
-  /* Proceed to store tokens. */
-  ephy_sync_service_set_token (self, crypto_keys, TOKEN_CRYPTOKEYS);
-  ephy_sync_secret_store_tokens (self);
+  /* Proceed to store secrets. */
+  ephy_sync_service_set_secret (self, secrets[CRYPTO_KEYS], crypto_keys);
+  ephy_sync_secret_store_secrets (self);
   is_internal_error = FALSE;
 
   g_free (crypto_keys);
@@ -1325,10 +1272,10 @@ ephy_sync_service_conclude_sign_in (EphySyncService *self,
   kB_hex = ephy_sync_crypto_encode_hex (kB, TOKEN_LENGTH);
 
   /* Save the email and the tokens. */
-  ephy_sync_service_set_user_email (self, data->email);
-  ephy_sync_service_set_token (self, data->uid, TOKEN_UID);
-  ephy_sync_service_set_token (self, data->sessionToken, TOKEN_SESSIONTOKEN);
-  ephy_sync_service_set_token (self, kB_hex, TOKEN_KB);
+  self->user_email = g_strdup (data->email);
+  ephy_sync_service_set_secret (self, secrets[UID], data->uid);
+  ephy_sync_service_set_secret (self, secrets[SESSION_TOKEN], data->sessionToken);
+  ephy_sync_service_set_secret (self, secrets[MASTER_KEY], kB_hex);
 
   ephy_sync_service_check_storage_version (self);
 
@@ -1461,13 +1408,12 @@ ephy_sync_service_do_sign_out (EphySyncService *self)
 {
   g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
 
-  /* Destroy session and delete tokens. */
   ephy_sync_service_stop_periodical_sync (self);
   ephy_sync_service_destroy_session (self);
   ephy_sync_service_clear_storage_credentials (self);
-  ephy_sync_service_clear_tokens (self);
-  ephy_sync_secret_forget_tokens ();
-  ephy_sync_service_set_user_email (self, NULL);
+  ephy_sync_secret_forget_secrets ();
+  g_hash_table_remove_all (self->secrets);
+  g_clear_pointer (&self->user_email, g_free);
 
   g_settings_set_string (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_USER, "");
 }
@@ -1861,6 +1807,19 @@ ephy_sync_service_sync_frequency_changed_cb (EphySyncService *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)
 {
diff --git a/src/sync/ephy-sync-service.h b/src/sync/ephy-sync-service.h
index 0d8590f..8c7d938 100644
--- a/src/sync/ephy-sync-service.h
+++ b/src/sync/ephy-sync-service.h
@@ -27,43 +27,30 @@
 
 G_BEGIN_DECLS
 
-typedef enum {
-  TOKEN_UID,
-  TOKEN_SESSIONTOKEN,
-  TOKEN_KB,
-  TOKEN_CRYPTOKEYS
-} EphySyncTokenType;
-
 #define EPHY_TYPE_SYNC_SERVICE (ephy_sync_service_get_type ())
 
 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);
-const char          *ephy_sync_service_get_user_email             (EphySyncService           *self);
-void                 ephy_sync_service_set_user_email             (EphySyncService           *self,
-                                                                   const char                *email);
-const char          *ephy_sync_service_get_token                  (EphySyncService           *self,
-                                                                   EphySyncTokenType          type);
-void                 ephy_sync_service_set_token                  (EphySyncService           *self,
-                                                                   const char                *value,
-                                                                   EphySyncTokenType          type);
-const char          *ephy_sync_service_token_name_from_type       (EphySyncTokenType          type);
-EphySyncTokenType    ephy_sync_service_token_type_from_name       (const char                *name);
-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);
-void                 ephy_sync_service_do_sign_in                 (EphySyncService           *self,
-                                                                   const char                *email,
-                                                                   const char                *uid,
-                                                                   const char                *sessionToken,
-                                                                   const char                *keyFetchToken,
-                                                                   const char                *unwrapBKey);
-void                 ephy_sync_service_do_sign_out                (EphySyncService           *self);
-void                 ephy_sync_service_do_sync                    (EphySyncService           *self);
-void                 ephy_sync_service_start_periodical_sync      (EphySyncService           *self);
-void                 ephy_sync_service_delete_synchronizable      (EphySyncService           *self,
-                                                                   EphySynchronizableManager *manager,
-                                                                   EphySynchronizable        
*synchronizable);
+EphySyncService   *ephy_sync_service_new                        (void);
+gboolean           ephy_sync_service_is_signed_in               (EphySyncService           *self);
+const char        *ephy_sync_service_get_user_email             (EphySyncService           *self);
+GHashTable        *ephy_sync_service_get_secrets                (EphySyncService           *self);
+const char        *ephy_sync_service_get_secret                 (EphySyncService           *self,
+                                                                 const char                *name);
+void               ephy_sync_service_set_secret                 (EphySyncService           *self,
+                                                                 const char                *name,
+                                                                 const char                *value);
+void               ephy_sync_service_do_sign_in                 (EphySyncService           *self,
+                                                                 const char                *email,
+                                                                 const char                *uid,
+                                                                 const char                *sessionToken,
+                                                                 const char                *keyFetchToken,
+                                                                 const char                *unwrapBKey);
+void               ephy_sync_service_do_sign_out                (EphySyncService           *self);
+void               ephy_sync_service_do_sync                    (EphySyncService           *self);
+void               ephy_sync_service_start_periodical_sync      (EphySyncService           *self);
+void               ephy_sync_service_delete_synchronizable      (EphySyncService           *self,
+                                                                 EphySynchronizableManager *manager,
+                                                                 EphySynchronizable        *synchronizable);
 
 G_END_DECLS


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