[epiphany/wip/ephy-sync] Implement new sign in method



commit e4b739e2d7c7fa8f302738efd4340961ee227a8b
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Fri Jul 15 18:22:23 2016 +0300

    Implement new sign in method

 src/ephy-sync-crypto.c        |  145 +++++++---------
 src/ephy-sync-crypto.h        |   65 ++++----
 src/ephy-sync-service.c       |  242 +++++++++-----------------
 src/ephy-sync-service.h       |   19 ++-
 src/ephy-sync-utils.c         |   15 +--
 src/ephy-sync-utils.h         |    7 +-
 src/prefs-dialog.c            |  387 ++++++++++++++++++++++++++---------------
 src/resources/prefs-dialog.ui |  169 +++++++------------
 8 files changed, 502 insertions(+), 547 deletions(-)
---
diff --git a/src/ephy-sync-crypto.c b/src/ephy-sync-crypto.c
index 01e9b27..37a9743 100644
--- a/src/ephy-sync-crypto.c
+++ b/src/ephy-sync-crypto.c
@@ -21,7 +21,6 @@
 
 #include <libsoup/soup.h>
 #include <nettle/hmac.h>
-#include <nettle/pbkdf2.h>
 #include <nettle/sha2.h>
 #include <string.h>
 
@@ -96,21 +95,6 @@ ephy_sync_crypto_hawk_header_new (gchar                       *header,
   return hawk_header;
 }
 
-static EphySyncCryptoStretchedCredentials *
-ephy_sync_crypto_stretched_credentials_new (guint8 *quickStretchedPW,
-                                            guint8 *authPW,
-                                            guint8 *unwrapBKey)
-{
-  EphySyncCryptoStretchedCredentials *stretched_credentials;
-
-  stretched_credentials = g_slice_new (EphySyncCryptoStretchedCredentials);
-  stretched_credentials->quickStretchedPW = quickStretchedPW;
-  stretched_credentials->authPW = authPW;
-  stretched_credentials->unwrapBKey = unwrapBKey;
-
-  return stretched_credentials;
-}
-
 static EphySyncCryptoProcessedKFT *
 ephy_sync_crypto_processed_kft_new (guint8 *tokenID,
                                     guint8 *reqHMACkey,
@@ -128,6 +112,21 @@ ephy_sync_crypto_processed_kft_new (guint8 *tokenID,
   return processed_kft;
 }
 
+static EphySyncCryptoProcessedST *
+ephy_sync_crypto_processed_st_new (guint8 *tokenID,
+                                   guint8 *reqHMACkey,
+                                   guint8 *requestKey)
+{
+  EphySyncCryptoProcessedST *processed_st;
+
+  processed_st = g_slice_new (EphySyncCryptoProcessedST);
+  processed_st->tokenID = tokenID;
+  processed_st->reqHMACkey = reqHMACkey;
+  processed_st->requestKey = requestKey;
+
+  return processed_st;
+}
+
 static EphySyncCryptoSyncKeys *
 ephy_sync_crypto_sync_keys_new (guint8 *kA,
                                 guint8 *kB,
@@ -192,18 +191,6 @@ ephy_sync_crypto_hawk_header_free (EphySyncCryptoHawkHeader *hawk_header)
 }
 
 void
-ephy_sync_crypto_stretched_credentials_free (EphySyncCryptoStretchedCredentials *stretched_credentials)
-{
-  g_return_if_fail (stretched_credentials != NULL);
-
-  g_free (stretched_credentials->quickStretchedPW);
-  g_free (stretched_credentials->authPW);
-  g_free (stretched_credentials->unwrapBKey);
-
-  g_slice_free (EphySyncCryptoStretchedCredentials, stretched_credentials);
-}
-
-void
 ephy_sync_crypto_processed_kft_free (EphySyncCryptoProcessedKFT *processed_kft)
 {
   g_return_if_fail (processed_kft != NULL);
@@ -217,6 +204,18 @@ ephy_sync_crypto_processed_kft_free (EphySyncCryptoProcessedKFT *processed_kft)
 }
 
 void
+ephy_sync_crypto_processed_st_free (EphySyncCryptoProcessedST *processed_st)
+{
+  g_return_if_fail (processed_st != NULL);
+
+  g_free (processed_st->tokenID);
+  g_free (processed_st->reqHMACkey);
+  g_free (processed_st->requestKey);
+
+  g_slice_free (EphySyncCryptoProcessedST, processed_st);
+}
+
+void
 ephy_sync_crypto_sync_keys_free (EphySyncCryptoSyncKeys *sync_keys)
 {
   g_return_if_fail (sync_keys != NULL);
@@ -468,21 +467,6 @@ append_token_to_header (gchar       *header,
 }
 
 /*
- * Runs 1000 iterations of PBKDF2.
- * Uses sha256 as hash function.
- */
-static void
-pbkdf2_1k (guint8 *key,
-           gsize   key_length,
-           guint8 *salt,
-           gsize   salt_length,
-           guint8 *out,
-           gsize   out_length)
-{
-  pbkdf2_hmac_sha256 (key_length, key, 1000, salt_length, salt, out_length, out);
-}
-
-/*
  * HMAC-based Extract-and-Expand Key Derivation Function.
  * Uses sha256 as hash function.
  * https://tools.ietf.org/html/rfc5869
@@ -540,46 +524,6 @@ hkdf (guint8 *in,
   g_free (prk);
 }
 
-EphySyncCryptoStretchedCredentials *
-ephy_sync_crypto_stretch (const gchar *emailUTF8,
-                          const gchar *passwordUTF8)
-{
-  gchar *salt_stretch;
-  gchar *info_auth;
-  gchar *info_unwrap;
-  guint8 *quickStretchedPW;
-  guint8 *authPW;
-  guint8 *unwrapBKey;
-
-  salt_stretch = ephy_sync_utils_kwe ("quickStretch", emailUTF8);
-  quickStretchedPW = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
-  pbkdf2_1k ((guint8 *) passwordUTF8, strlen (passwordUTF8),
-             (guint8 *) salt_stretch, strlen (salt_stretch),
-             quickStretchedPW, EPHY_SYNC_TOKEN_LENGTH);
-
-  info_auth = ephy_sync_utils_kw ("authPW");
-  authPW = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
-  hkdf (quickStretchedPW, EPHY_SYNC_TOKEN_LENGTH,
-        NULL, 0,
-        (guint8 *) info_auth, strlen (info_auth),
-        authPW, EPHY_SYNC_TOKEN_LENGTH);
-
-  info_unwrap = ephy_sync_utils_kw ("unwrapBkey");
-  unwrapBKey = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
-  hkdf (quickStretchedPW, EPHY_SYNC_TOKEN_LENGTH,
-        NULL, 0,
-        (guint8 *) info_unwrap, strlen (info_unwrap),
-        unwrapBKey, EPHY_SYNC_TOKEN_LENGTH);
-
-  g_free (salt_stretch);
-  g_free (info_unwrap);
-  g_free (info_auth);
-
-  return ephy_sync_crypto_stretched_credentials_new (quickStretchedPW,
-                                                     authPW,
-                                                     unwrapBKey);
-}
-
 EphySyncCryptoProcessedKFT *
 ephy_sync_crypto_process_key_fetch_token (const gchar *keyFetchToken)
 {
@@ -635,6 +579,41 @@ ephy_sync_crypto_process_key_fetch_token (const gchar *keyFetchToken)
                                              respXORkey);
 }
 
+EphySyncCryptoProcessedST *
+ephy_sync_crypto_process_session_token (const gchar *sessionToken)
+{
+  guint8 *st;
+  guint8 *out;
+  guint8 *tokenID;
+  guint8 *reqHMACkey;
+  guint8 *requestKey;
+  gchar *info;
+
+  st = ephy_sync_utils_decode_hex (sessionToken);
+  info = ephy_sync_utils_kw ("sessionToken");
+  out = g_malloc (3 * EPHY_SYNC_TOKEN_LENGTH);
+
+  hkdf (st, EPHY_SYNC_TOKEN_LENGTH,
+        NULL, 0,
+        (guint8 *) info, strlen (info),
+        out, 3 * EPHY_SYNC_TOKEN_LENGTH);
+
+  tokenID = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  reqHMACkey = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  requestKey = g_malloc (EPHY_SYNC_TOKEN_LENGTH);
+  memcpy (tokenID, out, EPHY_SYNC_TOKEN_LENGTH);
+  memcpy (reqHMACkey, out + EPHY_SYNC_TOKEN_LENGTH, EPHY_SYNC_TOKEN_LENGTH);
+  memcpy (requestKey, out + 2 * EPHY_SYNC_TOKEN_LENGTH, EPHY_SYNC_TOKEN_LENGTH);
+
+  g_free (st);
+  g_free (out);
+  g_free (info);
+
+  return ephy_sync_crypto_processed_st_new (tokenID,
+                                            reqHMACkey,
+                                            requestKey);
+}
+
 EphySyncCryptoSyncKeys *
 ephy_sync_crypto_retrieve_sync_keys (const gchar *bundle,
                                      guint8      *respHMACkey,
diff --git a/src/ephy-sync-crypto.h b/src/ephy-sync-crypto.h
index 2e3c789..33846ad 100644
--- a/src/ephy-sync-crypto.h
+++ b/src/ephy-sync-crypto.h
@@ -54,12 +54,6 @@ typedef struct {
 } EphySyncCryptoHawkHeader;
 
 typedef struct {
-  guint8 *quickStretchedPW;
-  guint8 *authPW;
-  guint8 *unwrapBKey;
-} EphySyncCryptoStretchedCredentials;
-
-typedef struct {
   guint8 *tokenID;
   guint8 *reqHMACkey;
   guint8 *respHMACkey;
@@ -67,47 +61,52 @@ typedef struct {
 } EphySyncCryptoProcessedKFT;
 
 typedef struct {
+  guint8 *tokenID;
+  guint8 *reqHMACkey;
+  guint8 *requestKey;
+} EphySyncCryptoProcessedST;
+
+typedef struct {
   guint8 *kA;
   guint8 *kB;
   guint8 *wrapKB;
 } EphySyncCryptoSyncKeys;
 
-EphySyncCryptoHawkOptions          *ephy_sync_crypto_hawk_options_new           (gchar *app,
-                                                                                 gchar *dlg,
-                                                                                 gchar *ext,
-                                                                                 gchar *content_type,
-                                                                                 gchar *hash,
-                                                                                 gchar *local_time_offset,
-                                                                                 gchar *nonce,
-                                                                                 gchar *payload,
-                                                                                 gchar *timestamp);
+EphySyncCryptoHawkOptions   *ephy_sync_crypto_hawk_options_new       (gchar *app,
+                                                                      gchar *dlg,
+                                                                      gchar *ext,
+                                                                      gchar *content_type,
+                                                                      gchar *hash,
+                                                                      gchar *local_time_offset,
+                                                                      gchar *nonce,
+                                                                      gchar *payload,
+                                                                      gchar *timestamp);
 
-void                                ephy_sync_crypto_hawk_options_free          (EphySyncCryptoHawkOptions 
*hawk_options);
+void                        ephy_sync_crypto_hawk_options_free       (EphySyncCryptoHawkOptions 
*hawk_options);
 
-void                                ephy_sync_crypto_hawk_header_free           (EphySyncCryptoHawkHeader 
*hawk_header);
+void                        ephy_sync_crypto_hawk_header_free        (EphySyncCryptoHawkHeader *hawk_header);
 
-void                                ephy_sync_crypto_stretched_credentials_free 
(EphySyncCryptoStretchedCredentials *stretched_credentials);
+void                        ephy_sync_crypto_processed_kft_free      (EphySyncCryptoProcessedKFT 
*processed_kft);
 
-void                                ephy_sync_crypto_processed_kft_free         (EphySyncCryptoProcessedKFT 
*processed_kft);
+void                        ephy_sync_crypto_processed_st_free       (EphySyncCryptoProcessedST 
*processed_st);
 
-void                                ephy_sync_crypto_sync_keys_free             (EphySyncCryptoSyncKeys 
*sync_keys);
+void                        ephy_sync_crypto_sync_keys_free          (EphySyncCryptoSyncKeys *sync_keys);
 
-EphySyncCryptoStretchedCredentials *ephy_sync_crypto_stretch                    (const gchar *emailUTF8,
-                                                                                 const gchar *passwordUTF8);
+EphySyncCryptoProcessedKFT *ephy_sync_crypto_process_key_fetch_token (const gchar *keyFetchToken);
 
-EphySyncCryptoProcessedKFT         *ephy_sync_crypto_process_key_fetch_token    (const gchar  
*keyFetchToken);
+EphySyncCryptoProcessedST  *ephy_sync_crypto_process_session_token   (const gchar *sessionToken);
 
-EphySyncCryptoSyncKeys             *ephy_sync_crypto_retrieve_sync_keys         (const gchar *bundle,
-                                                                                 guint8      *respHMACkey,
-                                                                                 guint8      *respXORkey,
-                                                                                 guint8      *unwrapBKey);
+EphySyncCryptoSyncKeys     *ephy_sync_crypto_retrieve_sync_keys      (const gchar *bundle,
+                                                                      guint8      *respHMACkey,
+                                                                      guint8      *respXORkey,
+                                                                      guint8      *unwrapBKey);
 
-EphySyncCryptoHawkHeader           *ephy_sync_crypto_compute_hawk_header        (const gchar               
*url,
-                                                                                 const gchar               
*method,
-                                                                                 const gchar               
*id,
-                                                                                 guint8                    
*key,
-                                                                                 gsize                      
key_length,
-                                                                                 EphySyncCryptoHawkOptions 
*options);
+EphySyncCryptoHawkHeader   *ephy_sync_crypto_compute_hawk_header     (const gchar               *url,
+                                                                      const gchar               *method,
+                                                                      const gchar               *id,
+                                                                      guint8                    *key,
+                                                                      gsize                      key_length,
+                                                                      EphySyncCryptoHawkOptions *options);
 
 G_END_DECLS
 
diff --git a/src/ephy-sync-service.c b/src/ephy-sync-service.c
index aa4f4f3..56651e2 100644
--- a/src/ephy-sync-service.c
+++ b/src/ephy-sync-service.c
@@ -43,15 +43,8 @@ struct _EphySyncService {
   GHashTable *tokens;
 };
 
-
 G_DEFINE_TYPE (EphySyncService, ephy_sync_service, G_TYPE_OBJECT);
 
-static void
-save_and_store_tokens (EphySyncService   *self,
-                       gchar             *token_value,
-                       EphySyncTokenType  token_type,
-                       ...) G_GNUC_NULL_TERMINATED;
-
 static guint
 synchronous_hawk_get_request (EphySyncService  *self,
                               const gchar      *endpoint,
@@ -77,12 +70,14 @@ LOG ("[%d] Sending synchronous HAWK GET request to %s endpoint", __LINE__, endpo
   soup_session_send_message (self->soup_session, message);
 LOG ("[%d] Got response from server: %u", __LINE__, message->status_code);
 
-  json_parser_load_from_data (self->parser,
-                              message->response_body->data,
-                              -1, NULL);
-  root = json_parser_get_root (self->parser);
-  g_assert (JSON_NODE_HOLDS_OBJECT (root));
-  *jobject = json_node_get_object (root);
+  if (jobject != NULL) {
+    json_parser_load_from_data (self->parser,
+                                message->response_body->data,
+                                -1, NULL);
+    root = json_parser_get_root (self->parser);
+    g_assert (JSON_NODE_HOLDS_OBJECT (root));
+    *jobject = json_node_get_object (root);
+  }
 
   g_free (url);
   ephy_sync_crypto_hawk_header_free (hawk_header);
@@ -129,12 +124,14 @@ LOG ("[%d] Sending synchronous HAWK POST request to %s endpoint", __LINE__, endp
   soup_session_send_message (self->soup_session, message);
 LOG ("[%d] Got response from server: %u", __LINE__, message->status_code);
 
-  json_parser_load_from_data (self->parser,
-                              message->response_body->data,
-                              -1, NULL);
-  root = json_parser_get_root (self->parser);
-  g_assert (JSON_NODE_HOLDS_OBJECT (root));
-  *jobject = json_node_get_object (root);
+  if (jobject != NULL) {
+    json_parser_load_from_data (self->parser,
+                                message->response_body->data,
+                                -1, NULL);
+    root = json_parser_get_root (self->parser);
+    g_assert (JSON_NODE_HOLDS_OBJECT (root));
+    *jobject = json_node_get_object (root);
+  }
 
   g_free (url);
   ephy_sync_crypto_hawk_options_free (hawk_options);
@@ -143,61 +140,6 @@ LOG ("[%d] Got response from server: %u", __LINE__, message->status_code);
   return message->status_code;
 }
 
-static guint
-synchronous_fxa_post_request (EphySyncService  *self,
-                              const gchar      *endpoint,
-                              gchar            *request_body,
-                              JsonObject      **jobject)
-{
-  SoupMessage *message;
-  JsonNode *root;
-  gchar *url;
-
-  url = g_strdup_printf ("%s%s%s", FXA_BASEURL, FXA_VERSION, endpoint);
-  message = soup_message_new (SOUP_METHOD_POST, url);
-  soup_message_set_request (message,
-                            "application/json",
-                            SOUP_MEMORY_TAKE,
-                            request_body,
-                            strlen (request_body));
-LOG ("[%d] Sending synchronous POST request to %s endpoint", __LINE__, endpoint);
-  soup_session_send_message (self->soup_session, message);
-LOG ("[%d] Got response from server: %u", __LINE__, message->status_code);
-
-  json_parser_load_from_data (self->parser,
-                              message->response_body->data,
-                              -1, NULL);
-  root = json_parser_get_root (self->parser);
-  g_assert (JSON_NODE_HOLDS_OBJECT (root));
-  *jobject = json_node_get_object (root);
-
-  g_free (url);
-
-  return message->status_code;
-}
-
-static void
-save_and_store_tokens (EphySyncService   *self,
-                       gchar             *token_value,
-                       EphySyncTokenType  token_type,
-                       ...)
-{
-  EphySyncTokenType type;
-  gchar *value;
-  va_list args;
-
-  ephy_sync_service_save_token (self, token_value, token_type);
-  ephy_sync_secret_store_token (self->user_email, token_value, token_type);
-
-  va_start (args, token_type);
-  while ((value = va_arg (args, gchar *)) != NULL) {
-    type = va_arg (args, EphySyncTokenType);
-    ephy_sync_service_save_token (self, value, type);
-    ephy_sync_secret_store_token (self->user_email, value, type);
-  }
-  va_end (args);
-}
-
 static void
 ephy_sync_service_finalize (GObject *object)
 {
@@ -255,10 +197,10 @@ ephy_sync_service_get_user_email (EphySyncService *self)
 
 void
 ephy_sync_service_set_user_email (EphySyncService *self,
-                                  const gchar     *emailUTF8)
+                                  const gchar     *email)
 {
   g_free (self->user_email);
-  self->user_email = g_strdup (emailUTF8);
+  self->user_email = g_strdup (email);
 }
 
 gchar *
@@ -293,15 +235,25 @@ LOG ("[%d] Saved token %s with value %s", __LINE__, token_name, token_value);
 }
 
 void
-ephy_sync_service_delete_token (EphySyncService   *self,
-                                EphySyncTokenType  token_type)
+ephy_sync_service_save_store_tokens (EphySyncService   *self,
+                                     gchar             *token_value,
+                                     EphySyncTokenType  token_type,
+                                     ...)
 {
-  const gchar *token_name;
+  EphySyncTokenType type;
+  gchar *value;
+  va_list args;
 
-  token_name = ephy_sync_utils_token_name_from_type (token_type);
-  g_hash_table_remove (self->tokens, token_name);
+  ephy_sync_service_save_token (self, token_value, token_type);
+  ephy_sync_secret_store_token (self->user_email, token_value, token_type);
 
-LOG ("[%d] Deleted token %s", __LINE__, token_name);
+  va_start (args, token_type);
+  while ((value = va_arg (args, gchar *)) != NULL) {
+    type = va_arg (args, EphySyncTokenType);
+    ephy_sync_service_save_token (self, value, type);
+    ephy_sync_secret_store_token (self->user_email, value, type);
+  }
+  va_end (args);
 }
 
 void
@@ -313,57 +265,48 @@ LOG ("[%d] Deleted all tokens", __LINE__);
 }
 
 gboolean
-ephy_sync_service_login (EphySyncService  *self,
-                         const gchar      *emailUTF8,
-                         const gchar      *passwordUTF8,
-                         gchar           **error_message)
+ephy_sync_service_destroy_session (EphySyncService *self,
+                                   const gchar     *sessionToken)
+{
+  EphySyncCryptoProcessedST *processed_st;
+  gchar *tokenID;
+  guint status_code;
+
+  g_return_val_if_fail (sessionToken != NULL, FALSE);
+
+  processed_st = ephy_sync_crypto_process_session_token (sessionToken);
+  tokenID = ephy_sync_utils_encode_hex (processed_st->tokenID, 0);
+
+  /* FIXME: Do this asynchronously, there is no need to wait for this. */
+  status_code = synchronous_hawk_post_request (self,
+                                               "session/destroy",
+                                               tokenID,
+                                               processed_st->reqHMACkey,
+                                               EPHY_SYNC_TOKEN_LENGTH,
+                                               g_strdup ("{}"),
+                                               NULL);
+
+  g_free (tokenID);
+  ephy_sync_crypto_processed_st_free (processed_st);
+
+  return status_code == STATUS_OK;
+}
+
+gboolean
+ephy_sync_service_fetch_sync_keys (EphySyncService *self,
+                                   const gchar     *email,
+                                   const gchar     *keyFetchToken,
+                                   const gchar     *unwrapBKey)
 {
-  EphySyncCryptoStretchedCredentials *stretched_credentials = NULL;
   EphySyncCryptoProcessedKFT *processed_kft = NULL;
   EphySyncCryptoSyncKeys *sync_keys = NULL;
   JsonObject *jobject;
-  gchar *request_body;
-  gchar *tokenID = NULL;
-  gchar *authPW = NULL;
-  gchar *unwrapBKey = NULL;
-  gchar *uid = NULL;
-  gchar *sessionToken = NULL;
-  gchar *keyFetchToken = NULL;
-  gchar *kA = NULL;
-  gchar *kB = NULL;
-  gchar *wrapKB = NULL;
+  guint8 *unwrapKB;
+  gchar *tokenID;
   guint status_code;
   gboolean retval = FALSE;
 
-  stretched_credentials = ephy_sync_crypto_stretch (emailUTF8, passwordUTF8);
-  authPW = ephy_sync_utils_encode_hex (stretched_credentials->authPW, 0);
-  request_body = ephy_sync_utils_build_json_string ("authPW", authPW,
-                                                    "email", emailUTF8,
-                                                    NULL);
-  status_code = synchronous_fxa_post_request (self,
-                                              "account/login?keys=true",
-                                              request_body,
-                                              &jobject);
-  if (status_code != STATUS_OK) {
-    g_warning ("FxA server errno: %ld, errmsg: %s",
-               json_object_get_int_member (jobject, "errno"),
-               json_object_get_string_member (jobject, "message"));
-    *error_message = g_strdup_printf ("%s.",
-                                      json_object_get_string_member (jobject, "message"));
-    g_free (authPW);
-    goto out;
-  } else if (json_object_get_boolean_member (jobject, "verified") == FALSE) {
-    g_warning ("Firefox Account not verified");
-    *error_message = g_strdup (_("Account not verified!"));
-    g_free (authPW);
-    goto out;
-  }
-
-  uid = g_strdup (json_object_get_string_member (jobject, "uid"));
-  sessionToken = g_strdup (json_object_get_string_member (jobject, "sessionToken"));
-  keyFetchToken = g_strdup (json_object_get_string_member (jobject, "keyFetchToken"));
-
-  /* Proceed with key fetching */
+  unwrapKB = ephy_sync_utils_decode_hex (unwrapBKey);
   processed_kft = ephy_sync_crypto_process_key_fetch_token (keyFetchToken);
   tokenID = ephy_sync_utils_encode_hex (processed_kft->tokenID, 0);
   status_code = synchronous_hawk_get_request (self,
@@ -376,52 +319,35 @@ ephy_sync_service_login (EphySyncService  *self,
     g_warning ("FxA server errno: %ld, errmsg: %s",
                json_object_get_int_member (jobject, "errno"),
                json_object_get_string_member (jobject, "message"));
-    /* Translators: the %s refers to the error message. */
-    *error_message = g_strdup_printf (_("Failed to retrieve keys: %s. Please try again."),
-                                      json_object_get_string_member (jobject, "message"));
-    g_free (authPW);
-    g_free (uid);
-    g_free (sessionToken);
-    g_free (keyFetchToken);
     goto out;
   }
 
   sync_keys = ephy_sync_crypto_retrieve_sync_keys (json_object_get_string_member (jobject, "bundle"),
                                                    processed_kft->respHMACkey,
                                                    processed_kft->respXORkey,
-                                                   stretched_credentials->unwrapBKey);
-  if (sync_keys == NULL) {
-    *error_message = g_strdup (_("Something went wrong, please try again."));
-    g_free (authPW);
-    g_free (uid);
-    g_free (sessionToken);
-    g_free (keyFetchToken);
+                                                   unwrapKB);
+
+  if (sync_keys == NULL)
     goto out;
-  }
 
-  /* Everything okay, save and store tokens */
-  ephy_sync_service_set_user_email (self, emailUTF8);
-  unwrapBKey = ephy_sync_utils_encode_hex (stretched_credentials->unwrapBKey, 0);
-  kA = ephy_sync_utils_encode_hex (sync_keys->kA, 0);
-  kB = ephy_sync_utils_encode_hex (sync_keys->kB, 0);
-  wrapKB = ephy_sync_utils_encode_hex (sync_keys->wrapKB, 0);
-  save_and_store_tokens (self,
-                         authPW, EPHY_SYNC_TOKEN_AUTHPW,
-                         unwrapBKey, EPHY_SYNC_TOKEN_UNWRAPBKEY,
-                         uid, EPHY_SYNC_TOKEN_UID,
-                         sessionToken, EPHY_SYNC_TOKEN_SESSIONTOKEN,
-                         keyFetchToken, EPHY_SYNC_TOKEN_KEYFETCHTOKEN,
-                         kA, EPHY_SYNC_TOKEN_KA,
-                         kB, EPHY_SYNC_TOKEN_KB,
-                         wrapKB, EPHY_SYNC_TOKEN_WRAPKB,
-                         NULL);
+  /* Everything is okay, save the tokens. */
+  ephy_sync_service_set_user_email (self, email);
+  ephy_sync_service_save_store_tokens (self,
+                                       g_strdup (keyFetchToken), EPHY_SYNC_TOKEN_KEYFETCHTOKEN,
+                                       g_strdup (unwrapBKey), EPHY_SYNC_TOKEN_UNWRAPBKEY,
+                                       ephy_sync_utils_encode_hex (sync_keys->kA, 0), EPHY_SYNC_TOKEN_KA,
+                                       ephy_sync_utils_encode_hex (sync_keys->kB, 0), EPHY_SYNC_TOKEN_KB,
+                                       NULL);
   retval = TRUE;
 
+LOG ("kA: %s", ephy_sync_utils_encode_hex (sync_keys->kA, 0));
+LOG ("kB: %s", ephy_sync_utils_encode_hex (sync_keys->kB, 0));
+
 out:
-  ephy_sync_crypto_stretched_credentials_free (stretched_credentials);
   ephy_sync_crypto_processed_kft_free (processed_kft);
   ephy_sync_crypto_sync_keys_free (sync_keys);
   g_free (tokenID);
+  g_free (unwrapKB);
 
   return retval;
 }
diff --git a/src/ephy-sync-service.h b/src/ephy-sync-service.h
index ffe63eb..9bc1a95 100644
--- a/src/ephy-sync-service.h
+++ b/src/ephy-sync-service.h
@@ -34,7 +34,7 @@ EphySyncService *ephy_sync_service_new               (void);
 gchar           *ephy_sync_service_get_user_email    (EphySyncService *self);
 
 void             ephy_sync_service_set_user_email    (EphySyncService *self,
-                                                      const gchar     *emailUTF8);
+                                                      const gchar     *email);
 
 gchar           *ephy_sync_service_get_token         (EphySyncService   *self,
                                                       EphySyncTokenType  token_type);
@@ -43,15 +43,20 @@ void             ephy_sync_service_save_token        (EphySyncService   *self,
                                                       gchar             *token_value,
                                                       EphySyncTokenType  token_type);
 
-void             ephy_sync_service_delete_token      (EphySyncService   *self,
-                                                      EphySyncTokenType  token_type);
+void             ephy_sync_service_save_store_tokens (EphySyncService   *self,
+                                                      gchar             *token_value,
+                                                      EphySyncTokenType  token_type,
+                                                      ...) G_GNUC_NULL_TERMINATED;
 
 void             ephy_sync_service_delete_all_tokens (EphySyncService *self);
 
-gboolean         ephy_sync_service_login             (EphySyncService  *self,
-                                                      const gchar      *emailUTF8,
-                                                      const gchar      *passwordUTF8,
-                                                      gchar           **error_message);
+gboolean         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);
 
 G_END_DECLS
 
diff --git a/src/ephy-sync-utils.c b/src/ephy-sync-utils.c
index 784b78e..d6b4425 100644
--- a/src/ephy-sync-utils.c
+++ b/src/ephy-sync-utils.c
@@ -31,13 +31,6 @@ ephy_sync_utils_kw (const gchar *name)
 }
 
 gchar *
-ephy_sync_utils_kwe (const gchar *name,
-                     const gchar *emailUTF8)
-{
-  return g_strconcat ("identity.mozilla.com/picl/v1/", name, ":", emailUTF8, NULL);
-}
-
-gchar *
 ephy_sync_utils_encode_hex (guint8 *data,
                             gsize   data_length)
 {
@@ -81,22 +74,18 @@ const gchar *
 ephy_sync_utils_token_name_from_type (EphySyncTokenType token_type)
 {
   switch (token_type) {
-  case EPHY_SYNC_TOKEN_AUTHPW:
-    return "authPW";
-  case EPHY_SYNC_TOKEN_UNWRAPBKEY:
-    return "unwrapBKey";
   case EPHY_SYNC_TOKEN_UID:
     return "uid";
   case EPHY_SYNC_TOKEN_SESSIONTOKEN:
     return "sessionToken";
   case EPHY_SYNC_TOKEN_KEYFETCHTOKEN:
     return "keyFetchToken";
+  case EPHY_SYNC_TOKEN_UNWRAPBKEY:
+    return "unwrapBKey";
   case EPHY_SYNC_TOKEN_KA:
     return "kA";
   case EPHY_SYNC_TOKEN_KB:
     return "kB";
-  case EPHY_SYNC_TOKEN_WRAPKB:
-    return "wrapKB";
   default:
     g_assert_not_reached ();
   }
diff --git a/src/ephy-sync-utils.h b/src/ephy-sync-utils.h
index a0ee2ec..501437f 100644
--- a/src/ephy-sync-utils.h
+++ b/src/ephy-sync-utils.h
@@ -26,21 +26,16 @@ G_BEGIN_DECLS
 #define EPHY_SYNC_TOKEN_LENGTH 32
 
 typedef enum {
-  EPHY_SYNC_TOKEN_AUTHPW,
-  EPHY_SYNC_TOKEN_UNWRAPBKEY,
   EPHY_SYNC_TOKEN_UID,
   EPHY_SYNC_TOKEN_SESSIONTOKEN,
   EPHY_SYNC_TOKEN_KEYFETCHTOKEN,
+  EPHY_SYNC_TOKEN_UNWRAPBKEY,
   EPHY_SYNC_TOKEN_KA,
   EPHY_SYNC_TOKEN_KB,
-  EPHY_SYNC_TOKEN_WRAPKB
 } EphySyncTokenType;
 
 gchar       *ephy_sync_utils_kw                   (const gchar *name);
 
-gchar       *ephy_sync_utils_kwe                  (const gchar *name,
-                                                   const gchar *emailUTF8);
-
 gchar       *ephy_sync_utils_encode_hex           (guint8 *data,
                                                    gsize   data_length);
 
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index 0117edf..3f4c49c 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -44,10 +44,20 @@
 
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <json-glib/json-glib.h>
 #include <string.h>
 
 #define DOWNLOAD_BUTTON_WIDTH   8
 
+static const gchar *fxa_url = "https://accounts.firefox.com/signin?service=sync&context=fx_ios_v1";;
+static const gchar *JSScript = "\"use strict\";"
+                               "function handleAccountsCommand(evt) {"
+                               "  let j = {type: evt.type, detail: evt.detail};"
+                               "  
window.webkit.messageHandlers.accountsCommandHandler.postMessage(JSON.stringify(j));"
+                               "};"
+                               "window.addEventListener(\"FirefoxAccountsCommand\", handleAccountsCommand);";
+
 enum {
   COL_LANG_NAME,
   COL_LANG_CODE
@@ -99,18 +109,16 @@ struct _PrefsDialog {
   GHashTable *iso_3166_table;
 
   /* sync */
-  GtkWidget *sync_top_box;
   GtkWidget *sync_authenticate_box;
-  GtkWidget *sync_login_grid;
-  GtkWidget *sync_logout_box;
-  GtkWidget *sync_email_entry;
-  GtkWidget *sync_password_entry;
-  GtkWidget *sync_login_button;
-  GtkWidget *sync_logout_button;
-  GtkWidget *sync_logout_details_label;
-  GtkWidget *sync_email_details_label;
-  GtkWidget *sync_password_details_label;
-  GtkWidget *sync_extra_details_label;
+  GtkWidget *sync_sign_in_box;
+  GtkWidget *sync_sign_in_details;
+  GtkWidget *sync_sign_out_box;
+  GtkWidget *sync_sign_out_details;
+  GtkWidget *sync_sign_out_button;
+
+  WebKitWebView *fxa_web_view;
+  WebKitUserContentManager *fxa_manager;
+  WebKitUserScript *fxa_script;
 };
 
 enum {
@@ -138,121 +146,257 @@ prefs_dialog_finalize (GObject *object)
   g_hash_table_destroy (dialog->iso_639_table);
   g_hash_table_destroy (dialog->iso_3166_table);
 
+  if (dialog->fxa_web_view != NULL) {
+    webkit_user_content_manager_unregister_script_message_handler (dialog->fxa_manager,
+                                                                   "accountsCommandHandler");
+    webkit_user_script_unref (dialog->fxa_script);
+  }
+
   G_OBJECT_CLASS (prefs_dialog_parent_class)->finalize (object);
 }
 
 static void
-on_manage_cookies_button_clicked (GtkWidget   *button,
-                                  PrefsDialog *dialog)
+inject_data_to_server (PrefsDialog *dialog,
+                       const gchar *type,
+                       const gchar *status,
+                       const gchar *data)
 {
-  EphyCookiesDialog *cookies_dialog;
+  gchar *json;
+  gchar *script;
 
-  cookies_dialog = ephy_cookies_dialog_new ();
+  if (data == NULL)
+    json = g_strdup_printf ("{'type': '%s', 'content': {'status': '%s'}}",
+                            type, status);
+  else
+    json = g_strdup_printf ("{'type': '%s', 'content': {'status': '%s', 'data': %s}}",
+                            type, status, data);
 
-  gtk_window_set_transient_for (GTK_WINDOW (cookies_dialog), GTK_WINDOW (dialog));
-  gtk_window_set_modal (GTK_WINDOW (cookies_dialog), TRUE);
-  gtk_window_present (GTK_WINDOW (cookies_dialog));
+  script = g_strdup_printf ("window.postMessage(%s, '%s');", json, fxa_url);
+
+  /* No callback, we don't expect any response from the server. */
+  webkit_web_view_run_javascript (dialog->fxa_web_view,
+                                  script,
+                                  NULL, NULL, NULL);
+
+  g_free (json);
+  g_free (script);
 }
 
-static void
-on_manage_passwords_button_clicked (GtkWidget   *button,
-                                    PrefsDialog *dialog)
+static gboolean
+sync_fxa_load_sign_in_url (PrefsDialog *dialog)
 {
-  EphyPasswordsDialog *passwords_dialog;
-
-  passwords_dialog = ephy_passwords_dialog_new ();
+  webkit_web_view_load_uri (dialog->fxa_web_view, fxa_url);
 
-  gtk_window_set_transient_for (GTK_WINDOW (passwords_dialog), GTK_WINDOW (dialog));
-  gtk_window_set_modal (GTK_WINDOW (passwords_dialog), TRUE);
-  gtk_window_present (GTK_WINDOW (passwords_dialog));
+  return G_SOURCE_REMOVE;
 }
 
 static void
-on_sync_login_button_clicked (GtkWidget   *button,
-                              PrefsDialog *dialog)
+server_message_received_cb (WebKitUserContentManager *manager,
+                            WebKitJavascriptResult   *result,
+                            PrefsDialog              *dialog)
 {
-  EphySyncService *sync_service;
-  const gchar *emailUTF8;
-  const gchar *passwordUTF8;
-  gboolean login_ok;
-  gchar *error_message = NULL;
-
-  gtk_label_set_markup (GTK_LABEL (dialog->sync_email_details_label), "");
-  gtk_label_set_markup (GTK_LABEL (dialog->sync_password_details_label), "");
-  gtk_label_set_markup (GTK_LABEL (dialog->sync_extra_details_label), "");
-
-  emailUTF8 = gtk_entry_get_text (GTK_ENTRY (dialog->sync_email_entry));
-  passwordUTF8 = gtk_entry_get_text (GTK_ENTRY (dialog->sync_password_entry));
-
-  if (emailUTF8 && !emailUTF8[0]) {
-    gtk_label_set_markup (GTK_LABEL (dialog->sync_email_details_label),
-                          _("<span fgcolor='#e6780b'>Please insert your email</span>"));
-    return;
+  EphySyncService *service;
+  GError *error = NULL;
+  JsonParser *parser;
+  JsonNode *root;
+  JsonObject *object;
+  JsonObject *detail;
+  JsonObject *data;
+  gchar *json_string;
+  const gchar *type;
+  const gchar *command;
+  const gchar *uid;
+  const gchar *email;
+  const gchar *sessionToken;
+  const gchar *keyFetchToken;
+  const gchar *unwrapBKey;
+  gboolean verified;
+
+  json_string = ephy_embed_utils_get_js_result_as_string (result);
+  parser = json_parser_new ();
+
+  if (json_parser_load_from_data (parser, json_string, -1, &error) == FALSE) {
+    g_warning ("Error loading JSON: %s", error->message);
+    g_error_free (error);
+    goto out;
   }
 
-  if (passwordUTF8 && !passwordUTF8[0]) {
-    gtk_label_set_markup (GTK_LABEL (dialog->sync_password_details_label),
-                          _("<span fgcolor='#e6780b'>Please insert your password</span>"));
-    return;
+  root = json_parser_get_root (parser);
+  object = json_node_get_object (root);
+  type = json_object_get_string_member (object, "type");
+
+  /* The only message type we can receive is FirefoxAccountsCommand. */
+  if (g_str_equal (type, "FirefoxAccountsCommand") == FALSE) {
+    g_warning ("Unknown command type: %s", type);
+    goto out;
   }
 
-LOG ("[%d] email: %s", __LINE__, emailUTF8);
-LOG ("[%d] password: %s", __LINE__, passwordUTF8);
-
-  sync_service = ephy_shell_get_global_sync_service ();
-  login_ok = ephy_sync_service_login (sync_service,
-                                      emailUTF8,
-                                      passwordUTF8,
-                                      &error_message);
-
-  if (login_ok == FALSE) {
-    /* Translators: the %s refers to the error message. */
-    gtk_label_set_markup (GTK_LABEL (dialog->sync_extra_details_label),
-                          g_strdup_printf (_("<span fgcolor='#e6780b'>Error: %s</span>"),
-                                           error_message));
-    g_free (error_message);
-    return;
+  detail = json_object_get_object_member (object, "detail");
+  command = json_object_get_string_member (detail, "command");
+
+  if (g_str_equal (command, "loaded")) {
+    LOG ("Loaded Firefox Sign In iframe");
+  } else if (g_str_equal (command, "can_link_account")) {
+    /* We need to confirm a relink. */
+    inject_data_to_server (dialog, "message", "can_link_account", "{'ok': true}");
+  } else if (g_str_equal (command, "login")) {
+    inject_data_to_server (dialog, "message", "login", NULL);
+    gtk_widget_set_visible (dialog->sync_sign_in_details, FALSE);
+
+    service = ephy_shell_get_global_sync_service ();
+
+    /* Extract tokens. */
+    data = json_object_get_object_member (detail, "data");
+    verified = json_object_get_boolean_member (data, "verified");
+    email = json_object_get_string_member (data, "email");
+    uid = json_object_get_string_member (data, "uid");
+    sessionToken = json_object_get_string_member (data, "sessionToken");
+    keyFetchToken = json_object_get_string_member (data, "keyFetchToken");
+    unwrapBKey = json_object_get_string_member (data, "unwrapBKey");
+
+    /* Cannot retrieve the sync keys without keyFetchToken or unwrapBKey. */
+    if (keyFetchToken == NULL || unwrapBKey == NULL) {
+      g_warning ("Ignoring login with keyFetchToken or unwrapBKey missing!"
+                 "Cannot retrieve sync keys with one of them missing.");
+      ephy_sync_service_destroy_session (service, sessionToken);
+      gtk_label_set_markup (GTK_LABEL (dialog->sync_sign_in_details),
+                          _("<span fgcolor='#e6780b'>Something went wrong, please try again.</span>"));
+      gtk_widget_set_visible (dialog->sync_sign_in_details, TRUE);
+      g_timeout_add_seconds (3, (GSourceFunc) sync_fxa_load_sign_in_url, dialog);
+      goto out;
+    }
+
+    /* Cannot retrieve the sync keys if account is not verified. */
+    if (verified == FALSE) {
+      g_warning ("Attempt to operate on an unverified account, giving up.");
+      ephy_sync_service_destroy_session (service, sessionToken);
+      gtk_label_set_markup (GTK_LABEL (dialog->sync_sign_in_details),
+                          _("<span fgcolor='#e6780b'>Please verify your account before you sign 
in.</span>"));
+      gtk_widget_set_visible (dialog->sync_sign_in_details, TRUE);
+      g_timeout_add_seconds (3, (GSourceFunc) sync_fxa_load_sign_in_url, dialog);
+      goto out;
+    }
+
+    /* We cannot sync without the sync keys. */
+    if (ephy_sync_service_fetch_sync_keys (service, email, keyFetchToken, unwrapBKey) == FALSE) {
+      g_warning ("Failed to retrieve the sync keys, giving up.");
+      ephy_sync_service_destroy_session (service, sessionToken);
+      gtk_label_set_markup (GTK_LABEL (dialog->sync_sign_in_details),
+                          _("<span fgcolor='#e6780b'>Something went wrong, please try again.</span>"));
+      gtk_widget_set_visible (dialog->sync_sign_in_details, TRUE);
+      g_timeout_add_seconds (3, (GSourceFunc) sync_fxa_load_sign_in_url, dialog);
+      goto out;
+    }
+
+    /* Everything is okay, save the tokens. */
+    g_settings_set_string (EPHY_SETTINGS_MAIN, EPHY_PREFS_SYNC_USER, email);
+    ephy_sync_service_save_store_tokens (service,
+                                         g_strdup (uid), EPHY_SYNC_TOKEN_UID,
+                                         g_strdup (sessionToken), EPHY_SYNC_TOKEN_SESSIONTOKEN,
+                                         NULL);
+
+    /* Translators: the %s refers to the email of the currently logged in user. */
+    gtk_label_set_markup (GTK_LABEL (dialog->sync_sign_out_details),
+                          g_strdup_printf (_("Currently logged in as <b>%s</b>"), email));
+    gtk_container_remove (GTK_CONTAINER (dialog->sync_authenticate_box),
+                          dialog->sync_sign_in_box);
+    gtk_box_pack_start (GTK_BOX (dialog->sync_authenticate_box),
+                        dialog->sync_sign_out_box,
+                        TRUE, TRUE, 0);
+  } else if (g_str_equal (command, "session_status")) {
+    /* We are not signed in at this time, which we signal by returning an error. */
+    inject_data_to_server (dialog, "message", "error", NULL);
+  } else if (g_str_equal (command, "sign_out")) {
+    /* We are not signed in at this time. We should never get a sign out message! */
+    inject_data_to_server (dialog, "message", "error", NULL);
   }
 
-  g_settings_set_string (EPHY_SETTINGS_MAIN,
-                         EPHY_PREFS_SYNC_USER,
-                         emailUTF8);
-  /* Translators: the %s refers to the email of the currently logged in user. */
-  gtk_label_set_markup (GTK_LABEL (dialog->sync_logout_details_label),
-                        g_strdup_printf (_("Currently logged in as <b>%s</b>"),
-                                         emailUTF8));
-  gtk_container_remove (GTK_CONTAINER (dialog->sync_authenticate_box),
-                        dialog->sync_login_grid);
-  gtk_box_pack_start (GTK_BOX (dialog->sync_authenticate_box),
-                      dialog->sync_logout_box,
-                      TRUE, TRUE, 0);
+out:
+  g_free (json_string);
+  g_object_unref (parser);
 }
 
 static void
-on_sync_logout_button_clicked (GtkWidget   *button,
-                               PrefsDialog *dialog)
+setup_fxa_sign_in_view (PrefsDialog *dialog)
 {
-  EphySyncService *sync_service;
+  dialog->fxa_script = webkit_user_script_new (JSScript,
+                                               WEBKIT_USER_CONTENT_INJECT_TOP_FRAME,
+                                               WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_END,
+                                               NULL, NULL);
+  dialog->fxa_manager = webkit_user_content_manager_new ();
+  webkit_user_content_manager_add_script (dialog->fxa_manager, dialog->fxa_script);
+  g_signal_connect (dialog->fxa_manager,
+                    "script-message-received::accountsCommandHandler",
+                    G_CALLBACK (server_message_received_cb),
+                    dialog);
+  webkit_user_content_manager_register_script_message_handler (dialog->fxa_manager,
+                                                               "accountsCommandHandler");
 
-  sync_service = ephy_shell_get_global_sync_service ();
+  dialog->fxa_web_view = WEBKIT_WEB_VIEW (webkit_web_view_new_with_user_content_manager 
(dialog->fxa_manager));
+  gtk_widget_set_visible (GTK_WIDGET (dialog->fxa_web_view), TRUE);
+  gtk_widget_set_size_request (GTK_WIDGET (dialog->fxa_web_view), 450, 450);
+  webkit_web_view_load_uri (dialog->fxa_web_view, fxa_url);
 
-  gtk_entry_set_text (GTK_ENTRY (dialog->sync_email_entry), "");
-  gtk_entry_set_text (GTK_ENTRY (dialog->sync_password_entry), "");
+  gtk_widget_set_visible (dialog->sync_sign_in_details, FALSE);
+  gtk_container_add (GTK_CONTAINER (dialog->sync_sign_in_box),
+                     GTK_WIDGET (dialog->fxa_web_view));
+}
+
+static void
+on_sync_sign_out_button_clicked (GtkWidget   *button,
+                                 PrefsDialog *dialog)
+{
+  EphySyncService *service;
+  gchar *sessionToken;
+
+  service = ephy_shell_get_global_sync_service ();
+  sessionToken = ephy_sync_service_get_token (service, EPHY_SYNC_TOKEN_SESSIONTOKEN);
 
-  /* TODO: Call session/destroy endpoint */
+  /* Destroy session and delete tokens. */
+  if (ephy_sync_service_destroy_session (service, sessionToken) == FALSE)
+    g_warning ("Failed to destroy session");
 
-  ephy_sync_service_delete_all_tokens (sync_service);
+  ephy_sync_service_delete_all_tokens (service);
   ephy_sync_secret_forget_all_tokens ();
+  g_settings_set_string (EPHY_SETTINGS_MAIN, EPHY_PREFS_SYNC_USER, "");
+
+  /* Show sign in box. */
+  if (dialog->fxa_web_view == NULL)
+    setup_fxa_sign_in_view (dialog);
+  else
+    webkit_web_view_load_uri (dialog->fxa_web_view, fxa_url);
 
-  g_settings_set_string (EPHY_SETTINGS_MAIN,
-                         EPHY_PREFS_SYNC_USER,
-                         "");
   gtk_container_remove (GTK_CONTAINER (dialog->sync_authenticate_box),
-                        dialog->sync_logout_box);
+                        dialog->sync_sign_out_box);
   gtk_box_pack_start (GTK_BOX (dialog->sync_authenticate_box),
-                      dialog->sync_login_grid,
+                      dialog->sync_sign_in_box,
                       TRUE, TRUE, 0);
-LOG ("[%d] logged out", __LINE__);
+}
+
+static void
+on_manage_cookies_button_clicked (GtkWidget   *button,
+                                  PrefsDialog *dialog)
+{
+  EphyCookiesDialog *cookies_dialog;
+
+  cookies_dialog = ephy_cookies_dialog_new ();
+
+  gtk_window_set_transient_for (GTK_WINDOW (cookies_dialog), GTK_WINDOW (dialog));
+  gtk_window_set_modal (GTK_WINDOW (cookies_dialog), TRUE);
+  gtk_window_present (GTK_WINDOW (cookies_dialog));
+}
+
+static void
+on_manage_passwords_button_clicked (GtkWidget   *button,
+                                    PrefsDialog *dialog)
+{
+  EphyPasswordsDialog *passwords_dialog;
+
+  passwords_dialog = ephy_passwords_dialog_new ();
+
+  gtk_window_set_transient_for (GTK_WINDOW (passwords_dialog), GTK_WINDOW (dialog));
+  gtk_window_set_modal (GTK_WINDOW (passwords_dialog), TRUE);
+  gtk_window_present (GTK_WINDOW (passwords_dialog));
 }
 
 static void
@@ -301,23 +445,16 @@ prefs_dialog_class_init (PrefsDialogClass *klass)
   gtk_widget_class_bind_template_child (widget_class, PrefsDialog, enable_spell_checking_checkbutton);
 
   /* sync */
-  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_top_box);
   gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_authenticate_box);
-  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_login_grid);
-  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_logout_box);
-  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_email_entry);
-  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_password_entry);
-  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_login_button);
-  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_logout_button);
-  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_logout_details_label);
-  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_email_details_label);
-  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_password_details_label);
-  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_extra_details_label);
+  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_sign_in_box);
+  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_sign_in_details);
+  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_sign_out_box);
+  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_sign_out_details);
+  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_sign_out_button);
 
   gtk_widget_class_bind_template_callback (widget_class, on_manage_cookies_button_clicked);
   gtk_widget_class_bind_template_callback (widget_class, on_manage_passwords_button_clicked);
-  gtk_widget_class_bind_template_callback (widget_class, on_sync_login_button_clicked);
-  gtk_widget_class_bind_template_callback (widget_class, on_sync_logout_button_clicked);
+  gtk_widget_class_bind_template_callback (widget_class, on_sync_sign_out_button_clicked);
 }
 
 static void
@@ -1349,48 +1486,22 @@ setup_language_page (PrefsDialog *dialog)
 static void
 setup_sync_page (PrefsDialog *dialog)
 {
-  GtkWidget *sync_main_label;
-  GtkWidget *sync_secondary_label;
   gchar *sync_user = NULL;
   gboolean logged_in;
 
-  sync_main_label = gtk_label_new (NULL);
-  gtk_widget_set_visible (sync_main_label, TRUE);
-  gtk_widget_set_halign (sync_main_label, GTK_ALIGN_START);
-  gtk_label_set_markup (GTK_LABEL (sync_main_label),
-                        _("Log in with your "
-                          "<a href=\"https://www.mozilla.org/en-US/firefox/accounts/\"; "
-                          "title=\"Get a Firefox Account\">Firefox Account</a> "
-                          "and have your data synced across all your devices.\n"));
-
-  sync_secondary_label = gtk_label_new (NULL);
-  gtk_widget_set_visible (sync_secondary_label, TRUE);
-  gtk_widget_set_halign (sync_secondary_label, GTK_ALIGN_START);
-  gtk_label_set_markup (GTK_LABEL (sync_secondary_label),
-                        _("Note that you must own an <b>already verified account</b> "
-                          "to be able to login."));
-
-  gtk_box_pack_start (GTK_BOX (dialog->sync_top_box),
-                      sync_main_label,
-                      TRUE, TRUE, 0);
-  gtk_box_pack_start (GTK_BOX (dialog->sync_top_box),
-                      sync_secondary_label,
-                      TRUE, TRUE, 0);
-
   sync_user = g_settings_get_string (EPHY_SETTINGS_MAIN, EPHY_PREFS_SYNC_USER);
   logged_in = sync_user && sync_user[0];
 
-  if (logged_in) {
-LOG ("[%d] Setup sync page, already logged in as %s", __LINE__, sync_user);
+  if (logged_in == FALSE) {
+    setup_fxa_sign_in_view (dialog);
     gtk_container_remove (GTK_CONTAINER (dialog->sync_authenticate_box),
-                          dialog->sync_login_grid);
-    /* Translators: the %s refers to the email of the currently logged in user. */
-    gtk_label_set_markup (GTK_LABEL (dialog->sync_logout_details_label),
-                          g_strdup_printf (_("Currently logged in as <b>%s</b>"), sync_user));
+                          dialog->sync_sign_out_box);
   } else {
-LOG ("[%d] Setup sync page, not logged in", __LINE__);
     gtk_container_remove (GTK_CONTAINER (dialog->sync_authenticate_box),
-                          dialog->sync_logout_box);
+                          dialog->sync_sign_in_box);
+    /* Translators: the %s refers to the email of the currently logged in user. */
+    gtk_label_set_markup (GTK_LABEL (dialog->sync_sign_out_details),
+                          g_strdup_printf (_("Currently logged in as <b>%s</b>"), sync_user));
   }
 }
 
diff --git a/src/resources/prefs-dialog.ui b/src/resources/prefs-dialog.ui
index b035cbf..e0ab0de 100644
--- a/src/resources/prefs-dialog.ui
+++ b/src/resources/prefs-dialog.ui
@@ -762,8 +762,24 @@
                           <object class="GtkBox" id="sync_top_box">
                             <property name="visible">True</property>
                             <property name="orientation">vertical</property>
-                            <property name="spacing">0</property>
                             <property name="margin-start">12</property>
+                            <property name="spacing">8</property>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="halign">start</property>
+                                <property name="use-markup">True</property>
+                                <property name="label" translatable="yes">Sign in with your &lt;b&gt;Firefox 
Account&lt;/b&gt; and have your data synced across all your devices.</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkLabel">
+                                <property name="visible">True</property>
+                                <property name="halign">start</property>
+                                <property name="use-markup">True</property>
+                                <property name="label" translatable="yes">Note that you must own an already 
&lt;b&gt;verified&lt;/b&gt; account to be able to login.</property>
+                              </object>
+                            </child>
                           </object>
                         </child>
                       </object>
@@ -776,7 +792,7 @@
                     <property name="orientation">vertical</property>
                     <property name="spacing">18</property>
                     <child>
-                      <object class="GtkBox" id="sync_authenticate_box">
+                      <object class="GtkBox">
                         <property name="visible">True</property>
                         <property name="orientation">vertical</property>
                         <property name="spacing">6</property>
@@ -791,122 +807,57 @@
                           </object>
                         </child>
                         <child>
-                          <object class="GtkGrid" id="sync_login_grid">
-                            <property name="visible">True</property>
-                            <property name="margin-start">12</property>
-                            <property name="row-spacing">6</property>
-                            <property name="column-spacing">12</property>
-                            <child>
-                              <object class="GtkEntry" id="sync_email_entry">
-                                <property name="visible">True</property>
-                                <property name="halign">start</property>
-                                <property name="max-length">80</property>
-                                <property name="width_request">230</property>
-                                <property name="activates-default">True</property>
-                                <property name="placeholder-text">Email</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">0</property>
-                                <property name="top-attach">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="sync_email_details_label">
-                                <property name="visible">True</property>
-                                <property name="halign">start</property>
-                                <property name="use-markup">True</property>
-                                <property name="label" translatable="yes"></property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">1</property>
-                                <property name="top-attach">0</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkEntry" id="sync_password_entry">
-                                <property name="visible">True</property>
-                                <property name="halign">start</property>
-                                <property name="max-length">80</property>
-                                <property name="width_request">230</property>
-                                <property name="activates-default">True</property>
-                                <property name="visibility">False</property>
-                                <property name="caps-lock-warning">True</property>
-                                <property name="placeholder-text">Password</property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">0</property>
-                                <property name="top-attach">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="sync_password_details_label">
-                                <property name="visible">True</property>
-                                <property name="halign">start</property>
-                                <property name="use-markup">True</property>
-                                <property name="label" translatable="yes"></property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">1</property>
-                                <property name="top-attach">1</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkButton" id="sync_login_button">
-                                <property name="label" translatable="yes">_Login</property>
-                                <property name="visible">True</property>
-                                <property name="use-underline">True</property>
-                                <property name="halign">start</property>
-                                <property name="width-request">100</property>
-                                <signal name="clicked" handler="on_sync_login_button_clicked"/>
-                                <style>
-                                  <class name="suggested-action"/>
-                                  <class name="text-button"/>
-                                </style>
-                              </object>
-                              <packing>
-                                <property name="left-attach">0</property>
-                                <property name="top-attach">2</property>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="sync_extra_details_label">
-                                <property name="visible">True</property>
-                                <property name="halign">start</property>
-                                <property name="use-markup">True</property>
-                                <property name="label" translatable="yes"></property>
-                              </object>
-                              <packing>
-                                <property name="left-attach">0</property>
-                                <property name="top-attach">3</property>
-                              </packing>
-                            </child>
-                          </object>
-                        </child>
-                        <child>
-                          <object class="GtkBox" id="sync_logout_box">
+                          <object class="GtkBox" id="sync_authenticate_box">
                             <property name="visible">True</property>
                             <property name="orientation">vertical</property>
-                            <property name="spacing">12</property>
                             <property name="margin-start">12</property>
                             <child>
-                              <object class="GtkLabel" id="sync_logout_details_label">
+                              <object class="GtkBox" id="sync_sign_in_box">
                                 <property name="visible">True</property>
-                                <property name="halign">start</property>
-                                <property name="label" translatable="yes"></property>
+                                <property name="orientation">vertical</property>
+                                <property name="halign">center</property>
+                                <property name="spacing">12</property>
+                                <child>
+                                  <object class="GtkLabel" id="sync_sign_in_details">
+                                    <property name="visible">False</property>
+                                    <property name="halign">start</property>
+                                  </object>
+                                </child>
                               </object>
                             </child>
                             <child>
-                              <object class="GtkButton" id="sync_logout_button">
-                                <property name="label" translatable="yes">Lo_gout</property>
+                              <object class="GtkBox" id="sync_sign_out_box">
                                 <property name="visible">True</property>
-                                <property name="use-underline">True</property>
-                                <property name="halign">start</property>
-                                <property name="width-request">100</property>
-                                <signal name="clicked" handler="on_sync_logout_button_clicked"/>
-                                <style>
-                                  <class name="destructive-action"/>
-                                  <class name="text-button"/>
-                                </style>
+                                <property name="orientation">vertical</property>
+                                <property name="spacing">8</property>
+                                <child>
+                                  <object class="GtkLabel" id="sync_sign_out_details">
+                                    <property name="visible">True</property>
+                                    <property name="halign">start</property>
+                                    <property name="label" translatable="yes"></property>
+                                  </object>
+                                </child>
+                                <child>
+                                  <object class="GtkLabel">
+                                    <property name="visible">True</property>
+                                    <property name="halign">start</property>
+                                    <property name="label" translatable="yes">Sign out if you wish to stop 
syncing data.</property>
+                                  </object>
+                                </child>
+                                <child>
+                                  <object class="GtkButton" id="sync_sign_out_button">
+                                    <property name="label" translatable="yes">Sign _out</property>
+                                    <property name="visible">True</property>
+                                    <property name="use-underline">True</property>
+                                    <property name="halign">start</property>
+                                    <property name="width-request">100</property>
+                                    <signal name="clicked" handler="on_sync_sign_out_button_clicked"/>
+                                    <style>
+                                      <class name="destructive-action"/>
+                                      <class name="text-button"/>
+                                    </style>
+                                  </object>
+                                </child>
                               </object>
                             </child>
                           </object>


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