[epiphany/wip/sync: 18/18] [wip] Implement history sync
- From: Gabriel Ivașcu <gabrielivascu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/wip/sync: 18/18] [wip] Implement history sync
- Date: Sat, 27 May 2017 20:10:07 +0000 (UTC)
commit e24b5c7ebf65c704f35ebaafa6c08bf5bd2b5327
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date: Wed May 24 00:20:07 2017 +0300
[wip] Implement history sync
data/org.gnome.epiphany.gschema.xml | 15 ++
lib/ephy-prefs.h | 3 +
lib/sync/ephy-history-manager.c | 216 +++++++++++++++++++++
lib/sync/ephy-history-manager.h | 36 ++++
lib/sync/ephy-history-record.c | 365 +++++++++++++++++++++++++++++++++++
lib/sync/ephy-history-record.h | 41 ++++
lib/sync/meson.build | 2 +
7 files changed, 678 insertions(+), 0 deletions(-)
---
diff --git a/data/org.gnome.epiphany.gschema.xml b/data/org.gnome.epiphany.gschema.xml
index 3635eed..e354664 100644
--- a/data/org.gnome.epiphany.gschema.xml
+++ b/data/org.gnome.epiphany.gschema.xml
@@ -322,6 +322,21 @@
<summary>Initial sync or normal sync</summary>
<description>TRUE if passwords collection needs to be synced for the first time,
FALSE otherwise.</description>
</key>
+ <key type="b" name="sync-history-enabled">
+ <default>false</default>
+ <summary>Enable history sync</summary>
+ <description>TRUE if history collection should be synced, FALSE
otherwise.</description>
+ </key>
+ <key type="d" name="sync-history-time">
+ <default>0</default>
+ <summary>History sync timestamp</summary>
+ <description>The timestamp at which last history sync was made.</description>
+ </key>
+ <key type="b" name="sync-history-initial">
+ <default>true</default>
+ <summary>Initial sync or normal sync</summary>
+ <description>TRUE if history collection needs to be synced for the first time, FALSE
otherwise.</description>
+ </key>
</schema>
<enum id="org.gnome.Epiphany.Permission">
<value nick="undecided" value="-1"/>
diff --git a/lib/ephy-prefs.h b/lib/ephy-prefs.h
index b6be084..fde68f9 100644
--- a/lib/ephy-prefs.h
+++ b/lib/ephy-prefs.h
@@ -162,6 +162,9 @@ static const char * const ephy_prefs_web_schema[] = {
#define EPHY_PREFS_SYNC_PASSWORDS_ENABLED "sync-passwords-enabled"
#define EPHY_PREFS_SYNC_PASSWORDS_TIME "sync-passwords-time"
#define EPHY_PREFS_SYNC_PASSWORDS_INITIAL "sync-passwords-initial"
+#define EPHY_PREFS_SYNC_HISTORY_ENABLED "sync-history-enabled"
+#define EPHY_PREFS_SYNC_HISTORY_TIME "sync-history-time"
+#define EPHY_PREFS_SYNC_HISTORY_INITIAL "sync-history-initial"
static struct {
const char *schema;
diff --git a/lib/sync/ephy-history-manager.c b/lib/sync/ephy-history-manager.c
new file mode 100644
index 0000000..646f5c1
--- /dev/null
+++ b/lib/sync/ephy-history-manager.c
@@ -0,0 +1,216 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany 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 Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "ephy-history-manager.h"
+
+#include "ephy-settings.h"
+#include "ephy-synchronizable-manager.h"
+
+struct _EphyHistoryManager {
+ GObject parent_instance;
+
+ EphyHistoryService *service;
+};
+
+static void ephy_synchronizable_manager_iface_init (EphySynchronizableManagerInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EphyHistoryManager, ephy_history_manager, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (EPHY_TYPE_SYNCHRONIZABLE_MANAGER,
+ ephy_synchronizable_manager_iface_init))
+
+enum {
+ PROP_0,
+ PROP_HISTORY_SERVICE,
+ LAST_PROP
+};
+
+static GParamSpec *obj_properties[LAST_PROP];
+
+static void
+ephy_history_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyHistoryManager *self = EPHY_HISTORY_MANAGER (object);
+
+ switch (prop_id) {
+ case PROP_HISTORY_SERVICE:
+ g_clear_object (&self->service);
+ self->service = g_object_ref (g_value_get_object (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_history_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyHistoryManager *self = EPHY_HISTORY_MANAGER (object);
+
+ switch (prop_id) {
+ case PROP_HISTORY_SERVICE:
+ g_value_set_object (value, self->service);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_history_manager_dispose (GObject *object)
+{
+ EphyHistoryManager *self = EPHY_HISTORY_MANAGER (object);
+
+ g_clear_object (&self->service);
+
+ G_OBJECT_CLASS (ephy_history_manager_parent_class)->dispose (object);
+}
+
+static void
+ephy_history_manager_class_init (EphyHistoryManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = ephy_history_manager_set_property;
+ object_class->get_property = ephy_history_manager_get_property;
+ object_class->dispose = ephy_history_manager_dispose;
+
+ obj_properties[PROP_HISTORY_SERVICE] =
+ g_param_spec_object ("history-service",
+ "History service",
+ "History Service",
+ EPHY_TYPE_HISTORY_SERVICE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+}
+
+static void
+ephy_history_manager_init (EphyHistoryManager *self)
+{
+}
+
+EphyHistoryManager *
+ephy_history_manager_new (EphyHistoryService *service)
+{
+ return EPHY_HISTORY_MANAGER (g_object_new (EPHY_TYPE_HISTORY_MANAGER,
+ "history-service", service,
+ NULL));
+}
+
+static const char *
+synchronizable_manager_get_collection_name (EphySynchronizableManager *manager)
+{
+ gboolean sync_with_firefox = g_settings_get_boolean (EPHY_SETTINGS_SYNC,
+ EPHY_PREFS_SYNC_WITH_FIREFOX);
+
+ return sync_with_firefox ? "history" : "ephy-history";
+}
+
+static GType
+synchronizable_manager_get_synchronizable_type (EphySynchronizableManager *manager)
+{
+ return EPHY_TYPE_HISTORY_RECORD;
+}
+
+static gboolean
+synchronizable_manager_is_initial_sync (EphySynchronizableManager *manager)
+{
+ return g_settings_get_boolean (EPHY_SETTINGS_SYNC,
+ EPHY_PREFS_SYNC_HISTORY_INITIAL);
+}
+
+static void
+synchronizable_manager_set_is_initial_sync (EphySynchronizableManager *manager,
+ gboolean is_initial)
+{
+ g_settings_set_boolean (EPHY_SETTINGS_SYNC,
+ EPHY_PREFS_SYNC_HISTORY_INITIAL,
+ is_initial);
+}
+
+static double
+synchronizable_manager_get_sync_time (EphySynchronizableManager *manager)
+{
+ return g_settings_get_double (EPHY_SETTINGS_SYNC,
+ EPHY_PREFS_SYNC_HISTORY_TIME);
+}
+
+static void
+synchronizable_manager_set_sync_time (EphySynchronizableManager *manager,
+ double sync_time)
+{
+ g_settings_set_double (EPHY_SETTINGS_SYNC,
+ EPHY_PREFS_SYNC_HISTORY_TIME,
+ sync_time);
+}
+
+static void
+synchronizable_manager_add (EphySynchronizableManager *manager,
+ EphySynchronizable *synchronizable)
+{
+ /* TODO: Implement this. */
+}
+
+static void
+synchronizable_manager_remove (EphySynchronizableManager *manager,
+ EphySynchronizable *synchronizable)
+{
+ /* TODO: Implement this. */
+}
+
+static void
+synchronizable_manager_save (EphySynchronizableManager *manager,
+ EphySynchronizable *synchronizable)
+{
+ /* TODO: Implement this. */
+}
+
+static void
+synchronizable_manager_merge (EphySynchronizableManager *manager,
+ gboolean is_initial,
+ GSList *remotes_deleted,
+ GSList *remotes_updated,
+ EphySynchronizableManagerMergeCallback callback,
+ gpointer user_data)
+{
+ /* TODO: Implement this. */
+}
+
+static void
+ephy_synchronizable_manager_iface_init (EphySynchronizableManagerInterface *iface)
+{
+ iface->get_collection_name = synchronizable_manager_get_collection_name;
+ iface->get_synchronizable_type = synchronizable_manager_get_synchronizable_type;
+ iface->is_initial_sync = synchronizable_manager_is_initial_sync;
+ iface->set_is_initial_sync = synchronizable_manager_set_is_initial_sync;
+ iface->get_sync_time = synchronizable_manager_get_sync_time;
+ iface->set_sync_time = synchronizable_manager_set_sync_time;
+ iface->add = synchronizable_manager_add;
+ iface->remove = synchronizable_manager_remove;
+ iface->save = synchronizable_manager_save;
+ iface->merge = synchronizable_manager_merge;
+}
diff --git a/lib/sync/ephy-history-manager.h b/lib/sync/ephy-history-manager.h
new file mode 100644
index 0000000..30f688c
--- /dev/null
+++ b/lib/sync/ephy-history-manager.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany 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 Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "ephy-history-record.h"
+#include "ephy-history-service.h"
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_HISTORY_MANAGER (ephy_history_manager_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyHistoryManager, ephy_history_manager, EPHY, HISTORY_MANAGER, GObject)
+
+EphyHistoryManager *ephy_history_manager_new (EphyHistoryService *service);
+
+G_END_DECLS
diff --git a/lib/sync/ephy-history-record.c b/lib/sync/ephy-history-record.c
new file mode 100644
index 0000000..5ba00ab
--- /dev/null
+++ b/lib/sync/ephy-history-record.c
@@ -0,0 +1,365 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany 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 Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "ephy-history-record.h"
+
+#include "ephy-synchronizable.h"
+
+struct _EphyHistoryRecord {
+ GObject parent_instance;
+
+ char *id;
+ char *title;
+ char *uri;
+ GSequence *visits;
+};
+
+static void json_serializable_iface_init (JsonSerializableIface *iface);
+static void ephy_synchronizable_iface_init (EphySynchronizableInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (EphyHistoryRecord, ephy_history_record, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE,
+ json_serializable_iface_init)
+ G_IMPLEMENT_INTERFACE (EPHY_TYPE_SYNCHRONIZABLE,
+ ephy_synchronizable_iface_init))
+
+enum {
+ PROP_0,
+ PROP_ID,
+ PROP_TITLE,
+ PROP_URI,
+ PROP_VISITS,
+ LAST_PROP
+};
+
+static GParamSpec *obj_properties[LAST_PROP];
+
+typedef struct {
+ gint64 timestamp; /* UNIX time in microseconds. */
+ guint type; /* Transition type.*/
+} EphyHistoryRecordVisit;
+
+static EphyHistoryRecordVisit *
+ephy_history_record_visit_new (gint64 timestamp,
+ guint type)
+{
+ EphyHistoryRecordVisit *visit;
+
+ visit = g_slice_new (EphyHistoryRecordVisit);
+ visit->timestamp = timestamp;
+ visit->type = type;
+
+ return visit;
+}
+
+static void
+ephy_history_record_visit_free (EphyHistoryRecordVisit *visit)
+{
+ g_assert (visit);
+
+ g_slice_free (EphyHistoryRecordVisit, visit);
+}
+
+static int
+ephy_history_record_visit_compare (EphyHistoryRecordVisit *visit1,
+ EphyHistoryRecordVisit *visit2,
+ gpointer user_data)
+{
+ g_assert (visit1);
+ g_assert (visit2);
+
+ /* We keep visits sorted in descending order by timestamp. */
+ return visit2->timestamp - visit1->timestamp;
+}
+
+static void
+ephy_history_record_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyHistoryRecord *self = EPHY_HISTORY_RECORD (object);
+
+ switch (prop_id) {
+ case PROP_ID:
+ g_free (self->id);
+ self->id = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_TITLE:
+ g_free (self->title);
+ self->title = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_URI:
+ g_free (self->uri);
+ self->uri = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_VISITS:
+ if (self->visits)
+ g_sequence_free (self->visits);
+ self->visits = g_value_get_pointer (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_history_record_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyHistoryRecord *self = EPHY_HISTORY_RECORD (object);
+
+ switch (prop_id) {
+ case PROP_ID:
+ g_value_set_string (value, self->id);
+ break;
+ case PROP_TITLE:
+ g_value_set_string (value, self->title);
+ break;
+ case PROP_URI:
+ g_value_set_string (value, self->uri);
+ break;
+ case PROP_VISITS:
+ g_value_set_pointer (value, self->visits);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_history_record_dispose (GObject *object)
+{
+ EphyHistoryRecord *self = EPHY_HISTORY_RECORD (object);
+
+ g_clear_pointer (&self->id, g_free);
+ g_clear_pointer (&self->title, g_free);
+ g_clear_pointer (&self->uri, g_free);
+ g_clear_pointer (&self->visits, g_sequence_free);
+
+ G_OBJECT_CLASS (ephy_history_record_parent_class)->dispose (object);
+}
+
+static void
+ephy_history_record_class_init (EphyHistoryRecordClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = ephy_history_record_set_property;
+ object_class->get_property = ephy_history_record_get_property;
+ object_class->dispose = ephy_history_record_dispose;
+
+ obj_properties[PROP_ID] =
+ g_param_spec_string ("id",
+ "Id",
+ "Id of the history record",
+ "Default id",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_TITLE] =
+ g_param_spec_string ("title",
+ "Title",
+ "Title of the history record",
+ "Default title",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_URI] =
+ g_param_spec_string ("histUri",
+ "History URI",
+ "URI of the history record",
+ "Default history uri",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_VISITS] =
+ g_param_spec_pointer ("visits",
+ "Visits",
+ "An array of how and when URI of the history record was visited",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+}
+
+static void
+ephy_history_record_init (EphyHistoryRecord *self)
+{
+}
+
+EphyHistoryRecord *
+ephy_history_record_new (const char *id,
+ const char *title,
+ const char *uri,
+ gint64 last_visit_time)
+{
+ EphyHistoryRecordVisit *visit;
+ GSequence *visits;
+
+ /* We only use TRANSITION_LINK for now. */
+ visit = ephy_history_record_visit_new (last_visit_time, 1);
+ visits = g_sequence_new ((GDestroyNotify)ephy_history_record_visit_free);
+ g_sequence_prepend (visits, visit);
+
+ return EPHY_HISTORY_RECORD (g_object_new (EPHY_TYPE_HISTORY_RECORD,
+ "id", id,
+ "title", title,
+ "histUri", uri,
+ "visits", visits,
+ NULL));
+}
+
+const char *
+ephy_history_record_get_id (EphyHistoryRecord *self)
+{
+ g_return_val_if_fail (EPHY_IS_HISTORY_RECORD (self), NULL);
+
+ return self->id;
+}
+
+const char *
+ephy_history_record_get_title (EphyHistoryRecord *self)
+{
+ g_return_val_if_fail (EPHY_IS_HISTORY_RECORD (self), NULL);
+
+ return self->title;
+}
+
+const char *
+ephy_history_record_get_uri (EphyHistoryRecord *self)
+{
+ g_return_val_if_fail (EPHY_IS_HISTORY_RECORD (self), NULL);
+
+ return self->uri;
+}
+
+gint64
+ephy_history_record_get_last_visit_time (EphyHistoryRecord *self)
+{
+ EphyHistoryRecordVisit *visit;
+
+ g_return_val_if_fail (EPHY_IS_HISTORY_RECORD (self), -1);
+ g_return_val_if_fail (self->visits, -1);
+
+ if (g_sequence_is_empty (self->visits))
+ return -1;
+
+ /* Visits are sorted in descending order by date. */
+ visit = (EphyHistoryRecordVisit *)g_sequence_get (g_sequence_get_begin_iter (self->visits));
+
+ return visit->timestamp;
+}
+
+static JsonNode *
+serializable_serialize_property (JsonSerializable *serializable,
+ const char *name,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ if (!g_strcmp0 (name, "visits")) {
+ JsonNode *node;
+ JsonArray *array;
+ GSequence *visits;
+ GSequenceIter *it;
+
+ node = json_node_new (JSON_NODE_ARRAY);
+ array = json_array_new ();
+ visits = g_value_get_pointer (value);
+
+ if (visits != NULL) {
+ for (it = g_sequence_get_begin_iter (visits); !g_sequence_iter_is_end (it); it = g_sequence_iter_next
(it)) {
+ EphyHistoryRecordVisit *visit = g_sequence_get (it);
+ JsonObject *object = json_object_new ();
+ json_object_set_int_member (object, "date", visit->timestamp);
+ json_object_set_int_member (object, "type", visit->type);
+ json_array_add_object_element (array, object);
+ }
+ }
+
+ json_node_set_array (node, array);
+
+ return node;
+ }
+
+ return json_serializable_default_serialize_property (serializable, name, value, pspec);;
+}
+
+static gboolean
+serializable_deserialize_property (JsonSerializable *serializable,
+ const char *name,
+ GValue *value,
+ GParamSpec *pspec,
+ JsonNode *node)
+{
+ if (!g_strcmp0 (name, "visits")) {
+ JsonArray *array;
+ GSequence *visits;
+
+ array = json_node_get_array (node);
+ visits = g_sequence_new ((GDestroyNotify)ephy_history_record_visit_free);
+
+ for (guint i = 0; i < json_array_get_length (array); i++) {
+ JsonObject *object = json_node_get_object (json_array_get_element (array, i));
+ gint64 timestamp = json_object_get_int_member (object, "date");
+ guint type = json_object_get_int_member (object, "type");
+ EphyHistoryRecordVisit *visit = ephy_history_record_visit_new (timestamp, type);
+ g_sequence_insert_sorted (visits, visit, (GCompareDataFunc)ephy_history_record_visit_compare, NULL);
+ }
+
+ g_value_set_pointer (value, visits);
+
+ return TRUE;
+ }
+
+ return json_serializable_default_deserialize_property (serializable, name, value, pspec, node);
+}
+
+static void
+json_serializable_iface_init (JsonSerializableIface *iface)
+{
+ iface->serialize_property = serializable_serialize_property;
+ iface->deserialize_property = serializable_deserialize_property;
+}
+
+static const char *
+synchronizable_get_id (EphySynchronizable *synchronizable)
+{
+ return ephy_history_record_get_id (EPHY_HISTORY_RECORD (synchronizable));
+}
+
+static double
+synchronizable_get_server_time_modified (EphySynchronizable *synchronizable)
+{
+ /* TODO: Implement this. */
+ return 0;
+}
+
+static void
+synchronizable_set_server_time_modified (EphySynchronizable *synchronizable,
+ double server_time_modified)
+{
+ /* TODO: Implement this. */
+}
+
+static void
+ephy_synchronizable_iface_init (EphySynchronizableInterface *iface)
+{
+ iface->get_id = synchronizable_get_id;
+ iface->get_server_time_modified = synchronizable_get_server_time_modified;
+ iface->set_server_time_modified = synchronizable_set_server_time_modified;
+ iface->to_bso = ephy_synchronizable_default_to_bso;
+}
diff --git a/lib/sync/ephy-history-record.h b/lib/sync/ephy-history-record.h
new file mode 100644
index 0000000..25ebcff
--- /dev/null
+++ b/lib/sync/ephy-history-record.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany 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 Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <json-glib/json-glib.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_HISTORY_RECORD (ephy_history_record_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyHistoryRecord, ephy_history_record, EPHY, HISTORY_RECORD, GObject)
+
+EphyHistoryRecord *ephy_history_record_new (const char *id,
+ const char *title,
+ const char *history_uri,
+ gint64 last_visit_time);
+const char *ephy_history_record_get_id (EphyHistoryRecord *self);
+const char *ephy_history_record_get_title (EphyHistoryRecord *self);
+const char *ephy_history_record_get_uri (EphyHistoryRecord *self);
+gint64 ephy_history_record_get_last_visit_time (EphyHistoryRecord *self);
+
+G_END_DECLS
diff --git a/lib/sync/meson.build b/lib/sync/meson.build
index 658c17c..b728c39 100644
--- a/lib/sync/meson.build
+++ b/lib/sync/meson.build
@@ -1,4 +1,6 @@
libephysync_sources = [
+ 'ephy-history-manager.c',
+ 'ephy-history-record.c',
'ephy-password-manager.c',
'ephy-password-record.c',
'ephy-sync-crypto.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]