[epiphany/wip/sync: 4/18] sync: Allow user to change device name



commit ca036b7be028611d42583e195dfe002a404cbcd3
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date:   Wed Jun 7 17:22:14 2017 +0300

    sync: Allow user to change device name

 data/org.gnome.epiphany.gschema.xml |   11 ++-
 lib/ephy-prefs.h                    |    3 +-
 lib/ephy-sync-utils.c               |   47 +++++++++
 lib/ephy-sync-utils.h               |    4 +
 lib/sync/ephy-open-tabs-manager.c   |   23 ++--
 lib/sync/ephy-sync-service.c        |  192 +++++++++++++++++++----------------
 lib/sync/ephy-sync-service.h        |    2 +
 src/prefs-dialog.c                  |   59 +++++++++++
 src/resources/gtk/prefs-dialog.ui   |   54 ++++++++++
 9 files changed, 292 insertions(+), 103 deletions(-)
---
diff --git a/data/org.gnome.epiphany.gschema.xml b/data/org.gnome.epiphany.gschema.xml
index e476eba..f0ccddd 100644
--- a/data/org.gnome.epiphany.gschema.xml
+++ b/data/org.gnome.epiphany.gschema.xml
@@ -277,10 +277,15 @@
                        <summary>Currently signed in sync user</summary>
                        <description>The email linked to the Firefox Account used to sync data with Mozilla’s 
servers.</description>
                </key>
-               <key type="s" name="sync-client-id">
+               <key type="s" name="sync-device-id">
                        <default>''</default>
-                       <summary>Sync client ID</summary>
-                       <description>The sync client ID of the current device.</description>
+                       <summary>Sync device ID</summary>
+                       <description>The sync device ID of the current device.</description>
+               </key>
+               <key type="s" name="sync-device-name">
+                       <default>''</default>
+                       <summary>Sync device name</summary>
+                       <description>The sync device name of the current device.</description>
                </key>
                <key type="u" name="sync-frequency">
                        <default>30</default>
diff --git a/lib/ephy-prefs.h b/lib/ephy-prefs.h
index 2cf31c2..6736296 100644
--- a/lib/ephy-prefs.h
+++ b/lib/ephy-prefs.h
@@ -153,7 +153,8 @@ static const char * const ephy_prefs_web_schema[] = {
 
 #define EPHY_PREFS_SYNC_SCHEMA            "org.gnome.Epiphany.sync"
 #define EPHY_PREFS_SYNC_USER              "sync-user"
-#define EPHY_PREFS_SYNC_CLIENT_ID         "sync-client-id"
+#define EPHY_PREFS_SYNC_DEVICE_ID         "sync-device-id"
+#define EPHY_PREFS_SYNC_DEVICE_NAME       "sync-device-name"
 #define EPHY_PREFS_SYNC_FREQUENCY         "sync-frequency"
 #define EPHY_PREFS_SYNC_WITH_FIREFOX      "sync-with-firefox"
 #define EPHY_PREFS_SYNC_BOOKMARKS_ENABLED "sync-bookmarks-enabled"
diff --git a/lib/ephy-sync-utils.c b/lib/ephy-sync-utils.c
index 011e925..dc4f9d7 100644
--- a/lib/ephy-sync-utils.c
+++ b/lib/ephy-sync-utils.c
@@ -21,6 +21,8 @@
 #include "config.h"
 #include "ephy-sync-utils.h"
 
+#include "ephy-settings.h"
+
 #include <libsoup/soup.h>
 #include <stdio.h>
 #include <string.h>
@@ -226,3 +228,48 @@ ephy_sync_utils_get_random_sync_id (void)
 
   return id;
 }
+
+void
+ephy_sync_utils_set_device_id (const char *id)
+{
+  g_return_if_fail (id);
+
+  g_settings_set_string (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_DEVICE_ID, id);
+}
+
+char *
+ephy_sync_utils_get_device_id (void)
+{
+  char *id;
+
+  id = g_settings_get_string (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_DEVICE_ID);
+  if (!g_strcmp0 (id, "")) {
+    g_free (id);
+    id = ephy_sync_utils_get_random_sync_id ();
+  }
+
+  return id;
+}
+
+void
+ephy_sync_utils_set_device_name (const char *name)
+{
+  g_return_if_fail (name);
+
+  g_settings_set_string (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_DEVICE_NAME, name);
+}
+
+char *
+ephy_sync_utils_get_device_name (void)
+{
+  char *name;
+
+  name = g_settings_get_string (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_DEVICE_NAME);
+  if (!g_strcmp0 (name, "")) {
+    g_free (name);
+    name = g_strdup_printf ("%s's Epiphany on %s",
+                            g_get_user_name (), g_get_host_name ());
+  }
+
+  return name;
+}
diff --git a/lib/ephy-sync-utils.h b/lib/ephy-sync-utils.h
index 502b85b..2bd7392 100644
--- a/lib/ephy-sync-utils.h
+++ b/lib/ephy-sync-utils.h
@@ -47,5 +47,9 @@ void    ephy_sync_utils_generate_random_bytes       (void         *random_ctx,
                                                      guint8       *out);
 char   *ephy_sync_utils_get_audience                (const char   *url);
 char   *ephy_sync_utils_get_random_sync_id          (void);
+void    ephy_sync_utils_set_device_id               (const char   *id);
+char   *ephy_sync_utils_get_device_id               (void);
+void    ephy_sync_utils_set_device_name             (const char   *name);
+char   *ephy_sync_utils_get_device_name             (void);
 
 G_END_DECLS
diff --git a/lib/sync/ephy-open-tabs-manager.c b/lib/sync/ephy-open-tabs-manager.c
index b9d7317..5331816 100644
--- a/lib/sync/ephy-open-tabs-manager.c
+++ b/lib/sync/ephy-open-tabs-manager.c
@@ -24,6 +24,7 @@
 #include "ephy-embed-container.h"
 #include "ephy-embed-shell.h"
 #include "ephy-settings.h"
+#include "ephy-sync-utils.h"
 #include "ephy-synchronizable-manager.h"
 
 struct _EphyOpenTabsManager {
@@ -79,8 +80,8 @@ ephy_open_tabs_manager_get_local_tabs (EphyOpenTabsManager *self)
   GList *windows;
   GList *tabs;
   char *favicon;
-  char *client_id;
-  char *client_name;
+  char *id;
+  char *name;
   const char *title;
   const char *url;
 
@@ -89,9 +90,9 @@ ephy_open_tabs_manager_get_local_tabs (EphyOpenTabsManager *self)
   embed_shell = ephy_embed_shell_get_default ();
   windows = gtk_application_get_windows (GTK_APPLICATION (embed_shell));
   database = webkit_web_context_get_favicon_database (ephy_embed_shell_get_web_context (embed_shell));
-  client_id = g_settings_get_string (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_CLIENT_ID);
-  client_name = g_strdup_printf ("%s on Epiphany", client_id);
-  local_tabs = ephy_open_tabs_record_new (client_id, client_name);
+  id = ephy_sync_utils_get_device_id ();
+  name = ephy_sync_utils_get_device_name ();
+  local_tabs = ephy_open_tabs_record_new (id, name);
 
   for (GList *l = windows; l && l->data; l = l->next) {
     tabs = ephy_embed_container_get_children (l->data);
@@ -112,8 +113,8 @@ ephy_open_tabs_manager_get_local_tabs (EphyOpenTabsManager *self)
     g_list_free (tabs);
   }
 
-  g_free (client_id);
-  g_free (client_name);
+  g_free (id);
+  g_free (name);
 
   return local_tabs;
 }
@@ -216,15 +217,15 @@ synchronizable_manager_merge (EphySynchronizableManager              *manager,
   EphyOpenTabsManager *self = EPHY_OPEN_TABS_MANAGER (manager);
   EphyOpenTabsRecord *local_tabs;
   GSList *to_upload = NULL;
-  char *client_id;
+  char *id;
 
-  client_id = g_settings_get_string (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_CLIENT_ID);
+  id = ephy_sync_utils_get_device_id ();
   g_slist_free_full (self->remote_records, g_object_unref);
   self->remote_records = NULL;
 
   for (GSList *l = remotes_updated; l && l->data; l = l->next) {
     /* Exclude the record which describes the local open tabs. */
-    if (!g_strcmp0 (client_id, ephy_open_tabs_record_get_id (l->data)))
+    if (!g_strcmp0 (id, ephy_open_tabs_record_get_id (l->data)))
       continue;
 
     self->remote_records = g_slist_prepend (self->remote_records, g_object_ref (l->data));
@@ -236,7 +237,7 @@ synchronizable_manager_merge (EphySynchronizableManager              *manager,
   local_tabs = ephy_open_tabs_manager_get_local_tabs (self);
   to_upload = g_slist_prepend (to_upload, local_tabs);
 
-  g_free (client_id);
+  g_free (id);
 
   callback (to_upload, TRUE, user_data);
 }
diff --git a/lib/sync/ephy-sync-service.c b/lib/sync/ephy-sync-service.c
index fea3ad1..fdb9a8c 100644
--- a/lib/sync/ephy-sync-service.c
+++ b/lib/sync/ephy-sync-service.c
@@ -1325,92 +1325,6 @@ ephy_sync_service_sync (gpointer user_data)
 }
 
 static void
-ephy_sync_service_unregister_client_id (EphySyncService *self)
-{
-  char *client_id;
-  char *endpoint;
-
-  g_assert (EPHY_IS_SYNC_SERVICE (self));
-
-  client_id = g_settings_get_string (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_CLIENT_ID);
-  endpoint = g_strdup_printf ("storage/clients/%s", client_id);
-
-  ephy_sync_service_queue_storage_request (self, endpoint, SOUP_METHOD_DELETE,
-                                           NULL, -1, -1, NULL, NULL);
-  g_free (endpoint);
-  endpoint = g_strdup_printf ("storage/tabs/%s", client_id);
-  ephy_sync_service_queue_storage_request (self, endpoint, SOUP_METHOD_DELETE,
-                                           NULL, -1, -1, NULL, NULL);
-  g_settings_set_string (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_CLIENT_ID, "");
-
-  g_free (endpoint);
-  g_free (client_id);
-}
-
-static void
-ephy_sync_service_register_client_id (EphySyncService *self)
-{
-  SyncCryptoKeyBundle *bundle;
-  JsonNode *node;
-  JsonObject *record;
-  JsonObject *payload;
-  JsonArray *array;
-  char *client_id;
-  char *name;
-  char *protocol;
-  char *payload_clear;
-  char *payload_cipher;
-  char *body;
-  char *endpoint;
-
-  g_assert (EPHY_IS_SYNC_SERVICE (self));
-
-  node = json_node_new (JSON_NODE_OBJECT);
-  record = json_object_new ();
-  payload = json_object_new ();
-  array = json_array_new ();
-  protocol = g_strdup_printf ("1.%d", STORAGE_VERSION);
-  json_array_add_string_element (array, protocol);
-  json_object_set_array_member (payload, "protocols", array);
-  client_id = ephy_sync_utils_get_random_sync_id ();
-  json_object_set_string_member (payload, "id", client_id);
-  name = g_strdup_printf ("%s on Epiphany", client_id);
-  json_object_set_string_member (payload, "name", name);
-  json_object_set_string_member (payload, "type", "desktop");
-  json_object_set_string_member (payload, "os", "Linux");
-  json_object_set_string_member (payload, "application", "Epiphany");
-  json_object_set_string_member (payload, "fxaDeviceId",
-                                 ephy_sync_service_get_secret (self, secrets[UID]));
-  json_object_set_string_member (payload, "version", VERSION);
-  json_object_set_null_member (payload, "appPackage");
-  json_node_set_object (node, payload);
-  payload_clear = json_to_string (node, FALSE);
-  bundle = ephy_sync_service_get_key_bundle (self, "clients");
-  payload_cipher = ephy_sync_crypto_encrypt_record (payload_clear, bundle);
-  json_object_set_string_member (record, "id", client_id);
-  json_object_set_string_member (record, "payload", payload_cipher);
-  json_node_set_object (node, record);
-  body = json_to_string (node, FALSE);
-  endpoint = g_strdup_printf ("storage/clients/%s", client_id);
-
-  ephy_sync_service_queue_storage_request (self, endpoint, SOUP_METHOD_PUT,
-                                           body, -1, -1, NULL, NULL);
-  g_settings_set_string (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_CLIENT_ID, client_id);
-
-  g_free (endpoint);
-  g_free (body);
-  g_free (payload_cipher);
-  ephy_sync_crypto_key_bundle_free (bundle);
-  g_free (payload_clear);
-  g_free (name);
-  g_free (client_id);
-  g_free (protocol);
-  json_object_unref(payload);
-  json_object_unref(record);
-  json_node_unref (node);
-}
-
-static void
 ephy_sync_service_stop_periodical_sync (EphySyncService *self)
 {
   g_assert (EPHY_IS_SYNC_SERVICE (self));
@@ -1566,7 +1480,7 @@ store_secrets_cb (SecretService   *service,
     g_clear_pointer (&self->account, g_free);
     g_hash_table_remove_all (self->secrets);
   } else {
-    ephy_sync_service_register_client_id (self);
+    ephy_sync_service_register_device (self, NULL);
   }
 
   g_signal_emit (self, signals[STORE_FINISHED], 0, error);
@@ -2228,13 +2142,115 @@ ephy_sync_service_unregister_manager (EphySyncService           *self,
   g_signal_handlers_disconnect_by_func (manager, synchronizable_modified_cb, self);
 }
 
+void
+ephy_sync_service_register_device (EphySyncService *self,
+                                   const char      *device_name)
+{
+  SyncCryptoKeyBundle *bundle;
+  JsonNode *node;
+  JsonObject *bso;
+  JsonObject *record;
+  JsonArray *array;
+  char *id;
+  char *name;
+  char *protocol;
+  char *cleartext;
+  char *encrypted;
+  char *body;
+  char *endpoint;
+
+  g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
+
+  /* Make protocol. */
+  protocol = g_strdup_printf ("1.%d", STORAGE_VERSION);
+  array = json_array_new ();
+  json_array_add_string_element (array, protocol);
+
+  /* Make device ID and name. */
+  id = ephy_sync_utils_get_device_id ();
+  if (device_name)
+    name = g_strdup (device_name);
+  else
+    name = ephy_sync_utils_get_device_name ();
+
+  /* Set record members. */
+  record = json_object_new ();
+  json_object_set_string_member (record, "id", id);
+  json_object_set_string_member (record, "fxaDeviceId",
+                                 ephy_sync_service_get_secret (self, secrets[UID]));
+  json_object_set_string_member (record, "name", name);
+  json_object_set_string_member (record, "type", "desktop");
+  json_object_set_string_member (record, "version", VERSION);
+  json_object_set_array_member (record, "protocols", array);
+  json_object_set_string_member (record, "os", "Linux");
+  json_object_set_null_member (record, "appPackage");
+  json_object_set_string_member (record, "application", "Epiphany");
+
+  /* Get record's string representation. */
+  node = json_node_new (JSON_NODE_OBJECT);
+  json_node_set_object (node, record);
+  cleartext = json_to_string (node, FALSE);
+
+  /* Make BSO as string. */
+  bundle = ephy_sync_service_get_key_bundle (self, "clients");
+  encrypted = ephy_sync_crypto_encrypt_record (cleartext, bundle);
+  bso = json_object_new ();
+  json_object_set_string_member (bso, "id", id);
+  json_object_set_string_member (bso, "payload", encrypted);
+  json_node_set_object (node, bso);
+  body = json_to_string (node, FALSE);
+
+  /* Upload BSO and store the new device ID and name. */
+  endpoint = g_strdup_printf ("storage/clients/%s", id);
+  ephy_sync_service_queue_storage_request (self, endpoint, SOUP_METHOD_PUT,
+                                           body, -1, -1, NULL, NULL);
+
+  ephy_sync_utils_set_device_id (id);
+  ephy_sync_utils_set_device_name (name);
+
+  g_free (endpoint);
+  g_free (body);
+  g_free (encrypted);
+  ephy_sync_crypto_key_bundle_free (bundle);
+  g_free (cleartext);
+  g_free (name);
+  g_free (id);
+  g_free (protocol);
+  json_object_unref (record);
+  json_object_unref (bso);
+  json_node_unref (node);
+}
+
+static void
+ephy_sync_service_unregister_device (EphySyncService *self)
+{
+  char *id;
+  char *endpoint;
+
+  g_assert (EPHY_IS_SYNC_SERVICE (self));
+
+  id = ephy_sync_utils_get_device_id ();
+  endpoint = g_strdup_printf ("storage/clients/%s", id);
+  ephy_sync_service_queue_storage_request (self, endpoint, SOUP_METHOD_DELETE,
+                                           NULL, -1, -1, NULL, NULL);
+
+  g_free (endpoint);
+  endpoint = g_strdup_printf ("storage/tabs/%s", id);
+  ephy_sync_service_queue_storage_request (self, endpoint, SOUP_METHOD_DELETE,
+                                           NULL, -1, -1, NULL, NULL);
+
+  ephy_sync_utils_set_device_id ("");
+
+  g_free (endpoint);
+  g_free (id);
+}
 
 void
 ephy_sync_service_do_sign_out (EphySyncService *self)
 {
   g_return_if_fail (EPHY_IS_SYNC_SERVICE (self));
 
-  ephy_sync_service_unregister_client_id (self);
+  ephy_sync_service_unregister_device (self);
   ephy_sync_service_stop_periodical_sync (self);
   ephy_sync_service_destroy_session (self, NULL);
   ephy_sync_service_clear_storage_credentials (self);
diff --git a/lib/sync/ephy-sync-service.h b/lib/sync/ephy-sync-service.h
index 369b9a6..30f9cbc 100644
--- a/lib/sync/ephy-sync-service.h
+++ b/lib/sync/ephy-sync-service.h
@@ -42,6 +42,8 @@ void               ephy_sync_service_do_sign_in             (EphySyncService *se
 void               ephy_sync_service_do_sign_out            (EphySyncService *self);
 void               ephy_sync_service_do_sync                (EphySyncService *self);
 void               ephy_sync_service_start_periodical_sync  (EphySyncService *self);
+void               ephy_sync_service_register_device        (EphySyncService *self,
+                                                             const char      *device_name);
 void               ephy_sync_service_register_manager       (EphySyncService           *self,
                                                              EphySynchronizableManager *manager);
 void               ephy_sync_service_unregister_manager     (EphySyncService           *self,
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index 8b16caa..e1ee4c0 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -39,6 +39,7 @@
 #include "ephy-shell.h"
 #include "ephy-string.h"
 #include "ephy-sync-service.h"
+#include "ephy-sync-utils.h"
 #include "ephy-uri-tester-shared.h"
 #include "clear-data-dialog.h"
 #include "cookies-dialog.h"
@@ -133,6 +134,10 @@ struct _PrefsDialog {
   GtkWidget *sync_frequency_60_min_radiobutton;
   GtkWidget *sync_now_button;
   GtkWidget *synced_tabs_button;
+  GtkWidget *sync_device_name_entry;
+  GtkWidget *sync_device_name_change_button;
+  GtkWidget *sync_device_name_save_button;
+  GtkWidget *sync_device_name_cancel_button;
   gboolean sync_was_signed_in;
 
   WebKitWebView *fxa_web_view;
@@ -576,6 +581,48 @@ on_sync_synced_tabs_button_clicked (GtkWidget   *button,
 }
 
 static void
+on_sync_device_name_change_button_clicked (GtkWidget   *button,
+                                           PrefsDialog *dialog)
+{
+  gtk_widget_set_sensitive (GTK_WIDGET (dialog->sync_device_name_entry), TRUE);
+  gtk_widget_set_visible (GTK_WIDGET (dialog->sync_device_name_change_button), FALSE);
+  gtk_widget_set_visible (GTK_WIDGET (dialog->sync_device_name_save_button), TRUE);
+  gtk_widget_set_visible (GTK_WIDGET (dialog->sync_device_name_cancel_button), TRUE);
+}
+
+static void
+on_sync_device_name_save_button_clicked (GtkWidget   *button,
+                                         PrefsDialog *dialog)
+{
+  const char *name;
+
+  name = gtk_entry_get_text (GTK_ENTRY (dialog->sync_device_name_entry));
+  ephy_sync_service_register_device (dialog->sync_service, name);
+
+  gtk_widget_set_sensitive (GTK_WIDGET (dialog->sync_device_name_entry), FALSE);
+  gtk_widget_set_visible (GTK_WIDGET (dialog->sync_device_name_change_button), TRUE);
+  gtk_widget_set_visible (GTK_WIDGET (dialog->sync_device_name_save_button), FALSE);
+  gtk_widget_set_visible (GTK_WIDGET (dialog->sync_device_name_cancel_button), FALSE);
+}
+
+static void
+on_sync_device_name_cancel_button_clicked (GtkWidget   *button,
+                                           PrefsDialog *dialog)
+{
+  char *name;
+
+  name = ephy_sync_utils_get_device_name ();
+  gtk_entry_set_text (GTK_ENTRY (dialog->sync_device_name_entry), name);
+
+  gtk_widget_set_sensitive (GTK_WIDGET (dialog->sync_device_name_entry), FALSE);
+  gtk_widget_set_visible (GTK_WIDGET (dialog->sync_device_name_change_button), TRUE);
+  gtk_widget_set_visible (GTK_WIDGET (dialog->sync_device_name_save_button), FALSE);
+  gtk_widget_set_visible (GTK_WIDGET (dialog->sync_device_name_cancel_button), FALSE);
+
+  g_free (name);
+}
+
+static void
 on_manage_cookies_button_clicked (GtkWidget   *button,
                                   PrefsDialog *dialog)
 {
@@ -689,6 +736,10 @@ prefs_dialog_class_init (PrefsDialogClass *klass)
   gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_frequency_60_min_radiobutton);
   gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_now_button);
   gtk_widget_class_bind_template_child (widget_class, PrefsDialog, synced_tabs_button);
+  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_device_name_entry);
+  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_device_name_change_button);
+  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_device_name_save_button);
+  gtk_widget_class_bind_template_child (widget_class, PrefsDialog, sync_device_name_cancel_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);
@@ -696,6 +747,9 @@ prefs_dialog_class_init (PrefsDialogClass *klass)
   gtk_widget_class_bind_template_callback (widget_class, on_sync_sign_out_button_clicked);
   gtk_widget_class_bind_template_callback (widget_class, on_sync_sync_now_button_clicked);
   gtk_widget_class_bind_template_callback (widget_class, on_sync_synced_tabs_button_clicked);
+  gtk_widget_class_bind_template_callback (widget_class, on_sync_device_name_change_button_clicked);
+  gtk_widget_class_bind_template_callback (widget_class, on_sync_device_name_save_button_clicked);
+  gtk_widget_class_bind_template_callback (widget_class, on_sync_device_name_cancel_button_clicked);
 }
 
 static void
@@ -1704,11 +1758,16 @@ setup_sync_page (PrefsDialog *dialog)
   GSettings *sync_settings;
   char *user;
   char *text;
+  char *name;
 
   sync_settings = ephy_settings_get (EPHY_PREFS_SYNC_SCHEMA);
   dialog->sync_service = ephy_shell_get_sync_service (ephy_shell_get_default ());
   dialog->sync_was_signed_in = ephy_sync_service_is_signed_in (dialog->sync_service);
 
+  name = ephy_sync_utils_get_device_name ();
+  gtk_entry_set_text (GTK_ENTRY (dialog->sync_device_name_entry), name);
+  g_free (name);
+
   if (!dialog->sync_was_signed_in) {
     sync_setup_firefox_iframe (dialog);
     gtk_container_remove (GTK_CONTAINER (dialog->sync_page_box),
diff --git a/src/resources/gtk/prefs-dialog.ui b/src/resources/gtk/prefs-dialog.ui
index ac32223..dbbc7ae 100644
--- a/src/resources/gtk/prefs-dialog.ui
+++ b/src/resources/gtk/prefs-dialog.ui
@@ -1028,6 +1028,60 @@
                             </child>
                           </object>
                         </child>
+                        <child>
+                          <object class="GtkLabel">
+                            <property name="visible">True</property>
+                            <property name="halign">start</property>
+                            <property name="label" translatable="yes">Device name</property>
+                            <attributes>
+                              <attribute name="weight" value="bold"/>
+                            </attributes>
+                          </object>
+                        </child>
+                        <child>
+                          <object class="GtkBox">
+                            <property name="visible">True</property>
+                            <property name="orientation">horizontal</property>
+                            <property name="spacing">6</property>
+                            <property name="margin-start">12</property>
+                            <child>
+                              <object class="GtkEntry" id="sync_device_name_entry">
+                                <property name="visible">True</property>
+                                <property name="hexpand">True</property>
+                                <property name="halign">start</property>
+                                <property name="width-request">250</property>
+                                <property name="sensitive">False</property>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkButton" id="sync_device_name_change_button">
+                                <property name="label" translatable="yes">_Change</property>
+                                <property name="visible">True</property>
+                                <property name="use-underline">True</property>
+                                <property name="halign">start</property>
+                                <signal name="clicked" handler="on_sync_device_name_change_button_clicked"/>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkButton" id="sync_device_name_save_button">
+                                <property name="label" translatable="yes">_Save</property>
+                                <property name="visible">False</property>
+                                <property name="use-underline">True</property>
+                                <property name="halign">start</property>
+                                <signal name="clicked" handler="on_sync_device_name_save_button_clicked"/>
+                              </object>
+                            </child>
+                            <child>
+                              <object class="GtkButton" id="sync_device_name_cancel_button">
+                                <property name="label" translatable="yes">_Cancel</property>
+                                <property name="visible">False</property>
+                                <property name="use-underline">True</property>
+                                <property name="halign">start</property>
+                                <signal name="clicked" handler="on_sync_device_name_cancel_button_clicked"/>
+                              </object>
+                            </child>
+                          </object>
+                        </child>
                       </object>
                     </child>
                   </object>


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