[epiphany/wip/ephy-sync: 1/48] ephy-sync: Add basic sync service and sync window
- From: Gabriel - Cristian Ivascu <gabrielivascu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/wip/ephy-sync: 1/48] ephy-sync: Add basic sync service and sync window
- Date: Sat, 20 Aug 2016 17:03:27 +0000 (UTC)
commit c2577444c34f9c0d77019aec66e37e0357100dd5
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date: Sun May 22 22:55:21 2016 +0300
ephy-sync: Add basic sync service and sync window
configure.ac | 4 +
src/Makefile.am | 6 +
src/ephy-shell.c | 57 +++++++
src/ephy-shell.h | 4 +
src/ephy-sync-crypto.c | 141 +++++++++++++++++
src/ephy-sync-crypto.h | 52 +++++++
src/ephy-sync-service.c | 164 ++++++++++++++++++++
src/ephy-sync-service.h | 46 ++++++
src/ephy-sync-window.c | 227 ++++++++++++++++++++++++++++
src/ephy-sync-window.h | 36 +++++
src/epiphany.gresource.xml | 1 +
src/resources/epiphany-application-menu.ui | 5 +
src/resources/sync-dialog.ui | 113 ++++++++++++++
src/window-commands.c | 16 ++
src/window-commands.h | 3 +
15 files changed, 875 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 1b2c67b..40c22ab 100644
--- a/configure.ac
+++ b/configure.ac
@@ -82,6 +82,8 @@ LIBNOTIFY_REQUIRED=0.5.1
GCR_REQUIRED=3.5.5
AVAHI_REQUIRED=0.6.22
GVDB_REQUIRED="glib-2.0 >= $GLIB_REQUIRED"
+NETTLE_REQUIRED=3.2
+JSON_GLIB_MIN_VERSION=0.14
# Tests
@@ -114,6 +116,8 @@ PKG_CHECK_MODULES([DEPENDENCIES], [
gcr-3 >= $GCR_REQUIRED
avahi-gobject >= $AVAHI_REQUIRED
avahi-client >= $AVAHI_REQUIRED
+ nettle >= NETTLE_REQUIRED
+ json-glib-1.0 >= $JSON_GLIB_MIN_VERSION
])
# Check requirements for gvdb
diff --git a/src/Makefile.am b/src/Makefile.am
index 22711cc..c2b936d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -55,6 +55,12 @@ libephymain_la_SOURCES = \
ephy-encoding-row.h \
ephy-history-window.c \
ephy-history-window.h \
+ ephy-sync-window.c \
+ ephy-sync-window.h \
+ ephy-sync-service.c \
+ ephy-sync-service.h \
+ ephy-sync-crypto.c \
+ ephy-sync-crypto.h \
ephy-link.c \
ephy-link.h \
ephy-location-controller.c \
diff --git a/src/ephy-shell.c b/src/ephy-shell.c
index 7c51744..14c7c8c 100644
--- a/src/ephy-shell.c
+++ b/src/ephy-shell.c
@@ -30,6 +30,7 @@
#include "ephy-file-helpers.h"
#include "ephy-gui.h"
#include "ephy-history-window.h"
+#include "ephy-sync-window.h"
#include "ephy-lockdown.h"
#include "ephy-prefs.h"
#include "ephy-private.h"
@@ -49,6 +50,7 @@ struct _EphyShell {
EphyEmbedShell parent_instance;
EphySession *session;
+ EphySyncService *global_sync_service;
GList *windows;
GObject *lockdown;
EphyBookmarks *bookmarks;
@@ -56,6 +58,7 @@ struct _EphyShell {
GNetworkMonitor *network_monitor;
GtkWidget *bme;
GtkWidget *history_window;
+ GtkWidget *sync_window;
GObject *prefs_dialog;
EphyShellStartupContext *local_startup_context;
EphyShellStartupContext *remote_startup_context;
@@ -183,6 +186,20 @@ show_history (GSimpleAction *action,
}
static void
+show_sync (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GtkWindow *window;
+
+LOG ("%s:%d", __func__, __LINE__);
+
+ window = gtk_application_get_active_window (GTK_APPLICATION (ephy_shell));
+
+ window_cmd_edit_sync (NULL, EPHY_WINDOW (window));
+}
+
+static void
show_preferences (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
@@ -243,6 +260,7 @@ static GActionEntry app_entries[] = {
{ "new-incognito", new_incognito_window, NULL, NULL, NULL },
{ "bookmarks", show_bookmarks, NULL, NULL, NULL },
{ "history", show_history, NULL, NULL, NULL },
+ { "sync", show_sync, NULL, NULL, NULL },
{ "preferences", show_preferences, NULL, NULL, NULL },
{ "shortcuts", show_shortcuts, NULL, NULL, NULL },
{ "help", show_help, NULL, NULL, NULL },
@@ -797,6 +815,26 @@ ephy_shell_get_bookmarks_editor (EphyShell *shell)
}
/**
+ * ephy_shell_get_global_sync_service:
+ *
+ * Return value: (transfer none):
+ **/
+GObject *
+ephy_shell_get_global_sync_service (EphyShell *shell)
+{
+ g_return_val_if_fail (EPHY_IS_SHELL (shell), NULL);
+
+ if (shell->global_sync_service == NULL) {
+LOG ("%s:%d", __func__, __LINE__);
+ shell->global_sync_service = ephy_sync_service_new ();
+ g_return_val_if_fail (shell->global_sync_service, NULL);
+ }
+
+LOG ("%s:%d", __func__, __LINE__);
+ return G_OBJECT (shell->global_sync_service);
+}
+
+/**
* ephy_shell_get_history_window:
*
* Return value: (transfer none):
@@ -822,6 +860,25 @@ ephy_shell_get_history_window (EphyShell *shell)
return shell->history_window;
}
+GtkWidget *
+ephy_shell_get_sync_window (EphyShell *shell)
+{
+ EphySyncService *sync_service;
+
+ if (shell->sync_window == NULL) {
+LOG ("%s:%d", __func__, __LINE__);
+ sync_service = EPHY_SYNC_SERVICE (ephy_shell_get_global_sync_service (shell));
+ shell->sync_window = ephy_sync_window_new (sync_service);
+ g_signal_connect (shell->sync_window,
+ "destroy",
+ G_CALLBACK (gtk_widget_destroyed),
+ &shell->sync_window);
+ }
+
+LOG ("%s:%d", __func__, __LINE__);
+ return shell->sync_window;
+}
+
/**
* ephy_shell_get_prefs_dialog:
*
diff --git a/src/ephy-shell.h b/src/ephy-shell.h
index 9ce4487..7c6b4f2 100644
--- a/src/ephy-shell.h
+++ b/src/ephy-shell.h
@@ -105,8 +105,12 @@ GtkWidget *ephy_shell_get_bookmarks_editor (EphyShell *shell);
EphyBookmarksManager *ephy_shell_get_bookmarks_manager (EphyShell *shell);
+GObject *ephy_shell_get_global_sync_service (EphyShell *shell);
+
GtkWidget *ephy_shell_get_history_window (EphyShell *shell);
+GtkWidget *ephy_shell_get_sync_window (EphyShell *shell);
+
GObject *ephy_shell_get_prefs_dialog (EphyShell *shell);
guint ephy_shell_get_n_windows (EphyShell *shell);
diff --git a/src/ephy-sync-crypto.c b/src/ephy-sync-crypto.c
new file mode 100644
index 0000000..056c7ce
--- /dev/null
+++ b/src/ephy-sync-crypto.c
@@ -0,0 +1,141 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2016 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ephy-debug.h"
+#include "ephy-sync-crypto.h"
+
+#include <nettle/hmac.h>
+#include <nettle/pbkdf2.h>
+#include <string.h>
+
+static const gchar hex_digits[] = "0123456789abcdef";
+
+gchar *
+ephy_sync_crypto_kw (const gchar *name)
+{
+ return g_strconcat ("identity.mozilla.com/picl/v1/", name, NULL);
+}
+
+gchar *
+ephy_sync_crypto_kwe (const gchar *name,
+ const gchar *emailUTF8)
+{
+ return g_strconcat ("identity.mozilla.com/picl/v1/", name, ":", emailUTF8, NULL);
+}
+
+gchar *
+ephy_sync_crypto_encode_hex (guint8 *data,
+ gsize data_length)
+{
+ gchar *retval = g_malloc (data_length * 2 + 1);
+
+ for (gsize i = 0; i < data_length; i++) {
+ guint8 byte = data[i];
+
+ retval[2 * i] = hex_digits[byte >> 4];
+ retval[2 * i + 1] = hex_digits[byte & 0xf];
+ }
+
+ retval[data_length * 2] = 0;
+
+ return retval;
+}
+
+/*
+ * Runs 1000 iterations of PBKDF2.
+ * Uses sha256 as hash function.
+ */
+void
+ephy_sync_crypto_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
+ */
+void
+ephy_sync_crypto_hkdf (guint8 *in,
+ gsize in_length,
+ guint8 *salt,
+ gsize salt_length,
+ guint8 *info,
+ gsize info_length,
+ guint8 *out,
+ gsize out_length)
+{
+ struct hmac_sha256_ctx ctx;
+ const gsize hash_length = 32;
+ gsize i, offset = 0;
+ guint8 *tmp, *prk;
+ guint8 counter;
+
+ if (out_length > hash_length * 255)
+ return;
+
+ /* If salt value was not provided, use an array of hash_length zeros */
+ if (salt == NULL) {
+ salt = g_malloc0 (hash_length);
+ salt_length = hash_length;
+ }
+
+ tmp = g_malloc0 (hash_length + info_length + 1);
+ prk = g_malloc0 (hash_length);
+
+ /* Step 1: Extract */
+ hmac_sha256_set_key (&ctx, salt_length, salt);
+ hmac_sha256_update (&ctx, in_length, in);
+ hmac_sha256_digest (&ctx, hash_length, prk);
+
+ /* Step 2: Expand */
+ hmac_sha256_set_key (&ctx, hash_length, prk);
+
+ for (i = 0, counter = 1; i < out_length; i += hash_length, counter++) {
+ memcpy (tmp + offset, info, info_length);
+ tmp[offset + info_length] = counter;
+
+ hmac_sha256_update (&ctx, offset + info_length + 1, tmp);
+ hmac_sha256_digest (&ctx, hash_length, tmp);
+
+ offset = hash_length;
+
+ memcpy (out + i, tmp, hash_length);
+ }
+
+ g_free (salt);
+ g_free (tmp);
+ g_free (prk);
+}
+
+/* FIXME: Only for debugging, remove when no longer needed */
+void
+ephy_sync_crypto_display_hex (guint8 *data,
+ gsize data_length,
+ const gchar *data_name)
+{
+LOG ("%s:", data_name);
+for (gsize i = 0; i < data_length; i++)
+ LOG ("%02x", data[i]);
+}
diff --git a/src/ephy-sync-crypto.h b/src/ephy-sync-crypto.h
new file mode 100644
index 0000000..cb83395
--- /dev/null
+++ b/src/ephy-sync-crypto.h
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2016 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EPHY_SYNC_CRYPTO_H
+#define EPHY_SYNC_CRYPTO_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+gchar *ephy_sync_crypto_kw (const gchar *name);
+gchar *ephy_sync_crypto_kwe (const gchar *name,
+ const gchar *emailUTF8);
+gchar *ephy_sync_crypto_encode_hex (guint8 *data,
+ gsize data_length);
+void ephy_sync_crypto_pbkdf2_1k (guint8 *key,
+ gsize key_length,
+ guint8 *salt,
+ gsize salt_length,
+ guint8 *out,
+ gsize out_length);
+void ephy_sync_crypto_hkdf (guint8 *in,
+ gsize in_length,
+ guint8 *salt,
+ gsize salt_length,
+ guint8 *info,
+ gsize info_length,
+ guint8 *out,
+ gsize out_length);
+/* FIXME: Only for debugging, remove when no longer needed */
+void ephy_sync_crypto_display_hex (guint8 *data,
+ gsize data_length,
+ const gchar *data_name);
+
+G_END_DECLS
+
+#endif
diff --git a/src/ephy-sync-service.c b/src/ephy-sync-service.c
new file mode 100644
index 0000000..a610f9a
--- /dev/null
+++ b/src/ephy-sync-service.c
@@ -0,0 +1,164 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2016 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ephy-debug.h"
+#include "ephy-sync-crypto.h"
+#include "ephy-sync-service.h"
+
+#include <json-glib/json-glib.h>
+#include <libsoup/soup.h>
+#include <string.h>
+
+struct _EphySyncService {
+ GObject parent_instance;
+};
+
+G_DEFINE_TYPE (EphySyncService, ephy_sync_service, G_TYPE_OBJECT);
+
+static void
+ephy_sync_service_class_init (EphySyncServiceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class = object_class; // suppress warnings
+
+LOG ("%s:%d", __func__, __LINE__);
+
+ // TODO: Set finalize, dispose, set/get property methods
+}
+
+static void
+ephy_sync_service_init (EphySyncService *self)
+{
+LOG ("%s:%d", __func__, __LINE__);
+}
+
+static void
+server_response_cb (SoupSession *session,
+ SoupMessage *message,
+ gpointer user_data)
+{
+ if (message->status_code == 200) {
+LOG ("response body: %s", message->response_body->data);
+ // TODO: parse response data using JsonParser
+ } else {
+LOG ("Error response from server: [%u] %s", message->status_code, message->reason_phrase);
+ }
+}
+
+EphySyncService *
+ephy_sync_service_new (void)
+{
+LOG ("%s:%d", __func__, __LINE__);
+
+ return EPHY_SYNC_SERVICE (g_object_new (EPHY_TYPE_SYNC_SERVICE,
+ NULL));
+}
+
+void
+ephy_sync_service_try_login (EphySyncService *self,
+ gboolean login_with_keys,
+ const gchar *emailUTF8,
+ guint8 *authPW,
+ guint8 *sessionToken,
+ guint8 *keyFetchToken)
+{
+ SoupSession *session;
+ SoupMessage *message;
+ char *request_body;
+ char *authPW_hex;
+
+ g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+
+LOG ("%s:%d", __func__, __LINE__);
+
+ session = soup_session_new_with_options (SOUP_SESSION_USER_AGENT,
+ "test-json",
+ NULL);
+ message = soup_message_new (SOUP_METHOD_POST,
+ "https://api.accounts.firefox.com/v1/account/login");
+
+ authPW_hex = ephy_sync_crypto_encode_hex (authPW, EPHY_SYNC_SERVICE_TOKEN_LENGTH);
+ request_body = g_strconcat ("{\"authPW\": \"",
+ authPW_hex,
+ "\", \"email\": \"",
+ emailUTF8,
+ "\"}",
+ NULL);
+
+ soup_message_set_request (message,
+ "application/json",
+ SOUP_MEMORY_COPY,
+ request_body,
+ strlen (request_body));
+
+ soup_session_queue_message (session, message, server_response_cb, NULL);
+
+ // TODO: find a way to safely free authPW_hex, request_body
+ // TODO: find a way to safely destroy session, message
+}
+
+void
+ephy_sync_service_stretch (EphySyncService *self,
+ const gchar *emailUTF8,
+ const gchar *passwordUTF8,
+ guint8 *authPW,
+ guint8 *unwrapBKey)
+{
+ gchar *salt_stretch;
+ gchar *info_auth;
+ gchar *info_unwrap;
+ guint8 *quickStretchedPW;
+
+ g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+
+LOG ("%s:%d", __func__, __LINE__);
+
+ salt_stretch = ephy_sync_crypto_kwe ("quickStretch", emailUTF8);
+ quickStretchedPW = g_malloc (EPHY_SYNC_SERVICE_TOKEN_LENGTH);
+ ephy_sync_crypto_pbkdf2_1k ((guint8 *) passwordUTF8,
+ strlen (passwordUTF8),
+ (guint8 *) salt_stretch,
+ strlen (salt_stretch),
+ quickStretchedPW,
+ EPHY_SYNC_SERVICE_TOKEN_LENGTH);
+
+ephy_sync_crypto_display_hex (quickStretchedPW, EPHY_SYNC_SERVICE_TOKEN_LENGTH, "quickStretchedPW");
+
+ info_auth = ephy_sync_crypto_kw ("authPW");
+ ephy_sync_crypto_hkdf (quickStretchedPW,
+ EPHY_SYNC_SERVICE_TOKEN_LENGTH,
+ NULL, 0,
+ (guint8 *) info_auth,
+ strlen (info_auth),
+ authPW,
+ EPHY_SYNC_SERVICE_TOKEN_LENGTH);
+
+ info_unwrap = ephy_sync_crypto_kw ("unwrapBkey");
+ ephy_sync_crypto_hkdf (quickStretchedPW,
+ EPHY_SYNC_SERVICE_TOKEN_LENGTH,
+ NULL, 0,
+ (guint8 *) info_unwrap,
+ strlen (info_unwrap),
+ unwrapBKey,
+ EPHY_SYNC_SERVICE_TOKEN_LENGTH);
+
+ g_free (salt_stretch);
+ g_free (info_unwrap);
+ g_free (info_auth);
+ g_free (quickStretchedPW);
+}
diff --git a/src/ephy-sync-service.h b/src/ephy-sync-service.h
new file mode 100644
index 0000000..9f6b2a7
--- /dev/null
+++ b/src/ephy-sync-service.h
@@ -0,0 +1,46 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2016 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EPHY_SYNC_SERVICE_H
+#define EPHY_SYNC_SERVICE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_SYNC_SERVICE (ephy_sync_service_get_type ())
+#define EPHY_SYNC_SERVICE_TOKEN_LENGTH 32
+
+G_DECLARE_FINAL_TYPE (EphySyncService, ephy_sync_service, EPHY, SYNC_SERVICE, GObject)
+
+EphySyncService *ephy_sync_service_new (void);
+void ephy_sync_service_stretch (EphySyncService *self,
+ const gchar *emailUTF8,
+ const gchar *passwordUTF8,
+ guint8 *authPW,
+ guint8 *unwrapBKey);
+void ephy_sync_service_try_login (EphySyncService *self,
+ gboolean login_with_keys,
+ const gchar *emailUTF8,
+ guint8 *authPW,
+ guint8 *sessionToken,
+ guint8 *keyFetchToken);
+
+G_END_DECLS
+
+#endif
diff --git a/src/ephy-sync-window.c b/src/ephy-sync-window.c
new file mode 100644
index 0000000..51dc2be
--- /dev/null
+++ b/src/ephy-sync-window.c
@@ -0,0 +1,227 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2016 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ephy-debug.h"
+#include "ephy-gui.h"
+#include "ephy-sync-crypto.h"
+#include "ephy-sync-window.h"
+
+#include <gtk/gtk.h>
+#include <string.h>
+
+struct _EphySyncWindow {
+ GtkDialog parent_instance;
+
+ EphySyncService *sync_service;
+ GCancellable *cancellable;
+
+ GtkWidget *entry_email;
+ GtkWidget *entry_password;
+ GtkButton *btn_submit;
+
+ GActionGroup *action_group;
+};
+
+G_DEFINE_TYPE (EphySyncWindow, ephy_sync_window, GTK_TYPE_DIALOG)
+
+enum {
+ PROP_0,
+ PROP_SYNC_SERVICE,
+ PROP_LAST
+};
+
+static GParamSpec *obj_properties[PROP_LAST];
+
+static void
+submit_action (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ const gchar *emailUTF8;
+ const gchar *passwordUTF8;
+ guint8 *authPW;
+ guint8 *unwrapBKey;
+ guint8 *sessionToken;
+ guint8 *keyFetchToken;
+ EphySyncWindow *self = EPHY_SYNC_WINDOW (user_data);
+
+ emailUTF8 = gtk_entry_get_text (GTK_ENTRY (self->entry_email));
+LOG ("email: %s", emailUTF8);
+ passwordUTF8 = gtk_entry_get_text (GTK_ENTRY (self->entry_password));
+LOG ("password: %s", passwordUTF8);
+
+ /* Only for easy testing */
+ if (!strlen (emailUTF8) && !strlen (passwordUTF8)) {
+ emailUTF8 = g_strdup ("andré@example.org");
+ passwordUTF8 = g_strdup ("pässwörd");
+ }
+
+ authPW = g_malloc (EPHY_SYNC_SERVICE_TOKEN_LENGTH);
+ unwrapBKey = g_malloc (EPHY_SYNC_SERVICE_TOKEN_LENGTH);
+ ephy_sync_service_stretch (self->sync_service,
+ emailUTF8,
+ passwordUTF8,
+ authPW,
+ unwrapBKey);
+ephy_sync_crypto_display_hex (authPW, EPHY_SYNC_SERVICE_TOKEN_LENGTH, "authPW");
+ephy_sync_crypto_display_hex (unwrapBKey, EPHY_SYNC_SERVICE_TOKEN_LENGTH, "unwrapBKey");
+
+ sessionToken = g_malloc (EPHY_SYNC_SERVICE_TOKEN_LENGTH);
+ keyFetchToken = g_malloc (EPHY_SYNC_SERVICE_TOKEN_LENGTH);
+ ephy_sync_service_try_login (self->sync_service,
+ FALSE,
+ emailUTF8,
+ authPW,
+ sessionToken,
+ keyFetchToken);
+ephy_sync_crypto_display_hex (sessionToken, EPHY_SYNC_SERVICE_TOKEN_LENGTH, "sessionToken");
+ephy_sync_crypto_display_hex (keyFetchToken, EPHY_SYNC_SERVICE_TOKEN_LENGTH, "keyFetchToken");
+
+ g_free (authPW);
+ g_free (unwrapBKey);
+ g_free (sessionToken);
+ g_free (keyFetchToken);
+}
+
+static void
+set_sync_service (EphySyncWindow *self,
+ EphySyncService *sync_service)
+{
+ if (sync_service == self->sync_service)
+ return;
+
+ if (self->sync_service != NULL) {
+ // TODO: Disconnect signal handlers, if any
+ g_clear_object (&self->sync_service);
+ }
+
+ if (sync_service != NULL) {
+ self->sync_service = g_object_ref (sync_service);
+ // TODO: Connect signal handlers, if any
+ }
+}
+
+static void
+ephy_sync_window_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphySyncWindow *self = EPHY_SYNC_WINDOW (object);
+
+ switch (prop_id) {
+ case PROP_SYNC_SERVICE:
+ set_sync_service (self, g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ephy_sync_window_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphySyncWindow *self = EPHY_SYNC_WINDOW (object);
+
+ switch (prop_id) {
+ case PROP_SYNC_SERVICE:
+ g_value_set_object (value, self->sync_service);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GActionGroup *
+create_action_group (EphySyncWindow *self)
+{
+ GSimpleActionGroup *group;
+
+ const GActionEntry entries[] = {
+ { "submit_action", submit_action }
+ };
+
+ group = g_simple_action_group_new ();
+ g_action_map_add_action_entries (G_ACTION_MAP (group), entries, G_N_ELEMENTS (entries), self);
+
+ return G_ACTION_GROUP (group);
+}
+
+static void
+ephy_sync_window_class_init (EphySyncWindowClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+LOG ("%s:%d", __func__, __LINE__);
+
+ object_class->set_property = ephy_sync_window_set_property;
+ object_class->get_property = ephy_sync_window_get_property;
+ // TODO: Set dispose method
+
+ obj_properties[PROP_SYNC_SERVICE] =
+ g_param_spec_object ("sync-service",
+ "Sync service",
+ "Sync Service",
+ EPHY_TYPE_SYNC_SERVICE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY);
+
+ g_object_class_install_properties (object_class, PROP_LAST, obj_properties);
+
+ gtk_widget_class_set_template_from_resource (widget_class,
+ "/org/gnome/epiphany/sync-dialog.ui");
+
+ gtk_widget_class_bind_template_child (widget_class, EphySyncWindow, entry_email);
+ gtk_widget_class_bind_template_child (widget_class, EphySyncWindow, entry_password);
+ gtk_widget_class_bind_template_child (widget_class, EphySyncWindow, btn_submit);
+}
+
+static void
+ephy_sync_window_init (EphySyncWindow *self)
+{
+LOG ("%s:%d", __func__, __LINE__);
+
+ gtk_widget_init_template (GTK_WIDGET (self));
+
+ self->cancellable = g_cancellable_new ();
+
+ ephy_gui_ensure_window_group (GTK_WINDOW (self));
+
+ self->action_group = create_action_group (self);
+ gtk_widget_insert_action_group (GTK_WIDGET (self), "sync", self->action_group);
+}
+
+GtkWidget *
+ephy_sync_window_new (EphySyncService *sync_service)
+{
+ EphySyncWindow *self;
+
+LOG ("%s:%d", __func__, __LINE__);
+
+ self = g_object_new (EPHY_TYPE_SYNC_WINDOW,
+ "use-header-bar", TRUE,
+ "sync-service", sync_service,
+ NULL);
+
+ return GTK_WIDGET (self);
+}
diff --git a/src/ephy-sync-window.h b/src/ephy-sync-window.h
new file mode 100644
index 0000000..0f95448
--- /dev/null
+++ b/src/ephy-sync-window.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2016 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef EPHY_SYNC_WINDOW_H
+#define EPHY_SYNC_WINDOW_H
+
+#include <gtk/gtk.h>
+
+#include "ephy-sync-service.h"
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_SYNC_WINDOW (ephy_sync_window_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphySyncWindow, ephy_sync_window, EPHY, SYNC_WINDOW, GtkDialog)
+
+GtkWidget *ephy_sync_window_new (EphySyncService *sync_service);
+
+G_END_DECLS
+
+#endif
diff --git a/src/epiphany.gresource.xml b/src/epiphany.gresource.xml
index 3212832..8c9b9cf 100644
--- a/src/epiphany.gresource.xml
+++ b/src/epiphany.gresource.xml
@@ -10,6 +10,7 @@
<file preprocess="xml-stripblanks" compressed="true">clear-data-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">cookies-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">history-dialog.ui</file>
+ <file preprocess="xml-stripblanks" compressed="true">sync-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">passwords-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">shortcuts-dialog.ui</file>
<file preprocess="xml-stripblanks" compressed="true">gtk/bookmark-properties-grid.ui</file>
diff --git a/src/resources/epiphany-application-menu.ui b/src/resources/epiphany-application-menu.ui
index bb0da59..c839232 100644
--- a/src/resources/epiphany-application-menu.ui
+++ b/src/resources/epiphany-application-menu.ui
@@ -29,6 +29,11 @@
<attribute name="action">app.history</attribute>
<attribute name="accel"><Primary>h</attribute>
</item>
+ <item>
+ <attribute name="label" translatable="yes">_Sync</attribute>
+ <attribute name="action">app.sync</attribute>
+ <attribute name="accel"><Primary>s</attribute>
+ </item>
</section>
<section>
<item>
diff --git a/src/resources/sync-dialog.ui b/src/resources/sync-dialog.ui
new file mode 100644
index 0000000..df88b37
--- /dev/null
+++ b/src/resources/sync-dialog.ui
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <requires lib="gtk+" version="3.10"/>
+
+ <template class="EphySyncWindow" parent="GtkDialog">
+ <property name="height_request">400</property>
+ <property name="modal">True</property>
+ <property name="window_position">center</property>
+ <property name="default_width">600</property>
+ <property name="default_height">400</property>
+ <property name="destroy_with_parent">True</property>
+ <property name="type_hint">dialog</property>
+ <child internal-child="headerbar">
+ <object class="GtkHeaderBar">
+ <property name="title" translatable="yes">Sync</property>
+ <property name="show-close-button">True</property>
+ </object>
+ </child>
+ <child internal-child="vbox">
+ <object class="GtkBox" id="dialog_vbox">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="spacing">2</property>
+ <child>
+ <object class="GtkGrid" id="grid">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="border_width">10</property>
+ <property name="row-spacing">6</property>
+ <property name="column-spacing">12</property>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Email</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="halign">start</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_email">
+ <property name="visible">True</property>
+ <property name="max-length">64</property>
+ <property name="width_request">200</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel">
+ <property name="label" translatable="yes">Password</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="xalign">0.5</property>
+ <property name="yalign">0.5</property>
+ <property name="halign">start</property>
+ <attributes>
+ <attribute name="weight" value="bold"/>
+ </attributes>
+ </object>
+ <packing>
+ <property name="left-attach">0</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkEntry" id="entry_password">
+ <property name="visible">True</property>
+ <property name="max-length">64</property>
+ <property name="width_request">200</property>
+ <property name="visibility">False</property>
+ <property name="caps-lock-warning">True</property>
+ </object>
+ <packing>
+ <property name="left-attach">1</property>
+ <property name="top-attach">1</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkButton" id="btn_submit">
+ <property name="label" translatable="yes">_Submit</property>
+ <property name="visible">True</property>
+ <property name="use-underline">True</property>
+ <property name="sensitive">True</property>
+ <property name="valign">center</property>
+ <property name="action-name">sync.submit_action</property>
+ <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>
+ </object>
+ </child>
+
+ </object>
+ </child>
+ </template>
+</interface>
diff --git a/src/window-commands.c b/src/window-commands.c
index 6b14b7e..cf16fcc 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -1334,6 +1334,22 @@ window_cmd_zoom_in (GSimpleAction *action,
}
void
+window_cmd_edit_sync (GtkAction *action,
+ EphyWindow *window)
+{
+ GtkWidget *swindow;
+
+LOG ("%s:%d", __func__, __LINE__);
+
+ swindow = ephy_shell_get_sync_window (ephy_shell_get_default ());
+
+ if (GTK_WINDOW (window) != gtk_window_get_transient_for (GTK_WINDOW (swindow)))
+ gtk_window_set_transient_for (GTK_WINDOW (swindow),
+ GTK_WINDOW (window));
+ gtk_window_present (GTK_WINDOW (swindow));
+}
+
+void
window_cmd_zoom_out (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
diff --git a/src/window-commands.h b/src/window-commands.h
index deaaa4c..6a6930d 100644
--- a/src/window-commands.h
+++ b/src/window-commands.h
@@ -177,6 +177,9 @@ void window_cmd_tabs_detach (GSimpleAction *action,
void window_cmd_tabs_close (GSimpleAction *action,
GVariant *parameter,
gpointer user_data);
+void window_cmd_edit_sync (GtkAction *action,
+ EphyWindow *window);
+
G_END_DECLS
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]