[epiphany] Add Chrome/Chromium bookmark importer
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany] Add Chrome/Chromium bookmark importer
- Date: Fri, 24 Apr 2020 16:38:53 +0000 (UTC)
commit 1b128214d310183e4443468ed3e92315fa810f64
Author: Jan-Michael Brummer <jan brummer tabos org>
Date: Tue Apr 21 19:46:27 2020 +0200
Add Chrome/Chromium bookmark importer
Fixes: https://gitlab.gnome.org/GNOME/epiphany/-/issues/352
src/bookmarks/ephy-bookmarks-import.c | 120 +++++++++++++++++++++++++++++
src/bookmarks/ephy-bookmarks-import.h | 4 +
src/window-commands.c | 138 ++++++++++++++++++++++++++++------
3 files changed, 241 insertions(+), 21 deletions(-)
---
diff --git a/src/bookmarks/ephy-bookmarks-import.c b/src/bookmarks/ephy-bookmarks-import.c
index de80a907b..e80745001 100644
--- a/src/bookmarks/ephy-bookmarks-import.c
+++ b/src/bookmarks/ephy-bookmarks-import.c
@@ -520,3 +520,123 @@ ephy_bookmarks_import_from_html (EphyBookmarksManager *manager,
parser_data_free (data);
return TRUE;
}
+
+static void chrome_import_folder (JsonObject *object,
+ GSequence *bookmarks);
+
+static void
+chrome_add_child (JsonArray *array,
+ guint index_,
+ JsonNode *element_node,
+ gpointer user_data)
+{
+ GSequence *bookmarks = user_data;
+ JsonObject *object = json_node_get_object (element_node);
+ const char *title;
+ const char *time;
+ const char *type;
+
+ if (!object)
+ return;
+
+ title = json_object_get_string_member (object, "name");
+ type = json_object_get_string_member (object, "type");
+ time = json_object_get_string_member (object, "date_added");
+
+ if (g_strcmp0 (type, "url") == 0) {
+ const char *url;
+
+ url = json_object_get_string_member (object, "url");
+
+ if (title && url && !g_str_has_prefix (url, "chrome://") && time) {
+ g_autofree const char *guid = ephy_bookmark_generate_random_id ();
+ EphyBookmark *bookmark;
+ GSequence *tags;
+ gint64 time_added;
+
+ tags = g_sequence_new (g_free);
+ time_added = g_ascii_strtoll (time, NULL, 0);
+
+ bookmark = ephy_bookmark_new (url, title, tags, guid);
+ ephy_bookmark_set_time_added (bookmark, time_added);
+ ephy_synchronizable_set_server_time_modified (EPHY_SYNCHRONIZABLE (bookmark), time_added);
+
+ g_sequence_prepend (bookmarks, bookmark);
+ }
+ } else if (g_strcmp0 (type, "folder") == 0) {
+ chrome_import_folder (object, bookmarks);
+ }
+}
+
+static void
+chrome_import_folder (JsonObject *object,
+ GSequence *bookmarks)
+{
+ JsonArray *children;
+ const char *type;
+
+ type = json_object_get_string_member (object, "type");
+ if (g_strcmp0 (type, "folder") != 0)
+ return;
+
+ children = json_object_get_array_member (object, "children");
+ if (children)
+ json_array_foreach_element (children, chrome_add_child, bookmarks);
+}
+
+static void
+chrome_parse_root (JsonObject *object,
+ const gchar *member_name,
+ JsonNode *member_node,
+ gpointer user_data)
+{
+ JsonObject *member_object;
+
+ member_object = json_node_get_object (member_node);
+ chrome_import_folder (member_object, user_data);
+}
+
+gboolean
+ephy_bookmarks_import_from_chrome (EphyBookmarksManager *manager,
+ const char *filename,
+ GError **error)
+{
+ g_autoptr (GSequence) bookmarks = NULL;
+ g_autoptr (JsonParser) parser = NULL;
+ JsonNode *root;
+ JsonObject *object;
+ JsonObject *roots_object;
+
+ parser = json_parser_new ();
+
+ if (!json_parser_load_from_file (parser, filename, error))
+ return FALSE;
+
+ root = json_parser_get_root (parser);
+ if (!root)
+ goto parser_error;
+
+ object = json_node_get_object (root);
+ if (!object)
+ goto parser_error;
+
+ roots_object = json_object_get_object_member (object, "roots");
+ if (!roots_object)
+ goto parser_error;
+
+ bookmarks = g_sequence_new (g_object_unref);
+
+ json_object_foreach_member (roots_object, chrome_parse_root, bookmarks);
+
+ ephy_bookmarks_manager_add_bookmarks (manager, bookmarks);
+
+ return TRUE;
+
+parser_error:
+ g_set_error (error,
+ BOOKMARKS_IMPORT_ERROR,
+ BOOKMARKS_IMPORT_ERROR_BOOKMARKS,
+ _("Bookmarks file could not be parsed:"));
+
+ return FALSE;
+}
diff --git a/src/bookmarks/ephy-bookmarks-import.h b/src/bookmarks/ephy-bookmarks-import.h
index 972d70baf..33b804ad6 100644
--- a/src/bookmarks/ephy-bookmarks-import.h
+++ b/src/bookmarks/ephy-bookmarks-import.h
@@ -40,4 +40,8 @@ gboolean ephy_bookmarks_import_from_html (EphyBookmarksManager *manager,
const char *filename,
GError **error);
+gboolean ephy_bookmarks_import_from_chrome (EphyBookmarksManager *manager,
+ const char *filename,
+ GError **error);
+
G_END_DECLS
diff --git a/src/window-commands.c b/src/window-commands.c
index 92c523b2d..072c81b6a 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -93,10 +93,28 @@ window_cmd_new_incognito_window (GSimpleAction *action,
ephy_open_incognito_window (NULL);
}
-const gchar *import_option_names[3] = {
- N_("GVDB File"),
- N_("HTML File"),
- N_("Firefox")
+typedef enum {
+ IMPORT_TYPE_CHOOSE,
+ IMPORT_TYPE_IMPORT
+} ImportTypes;
+
+
+struct import_option {
+ const char *name;
+ ImportTypes type;
+ gboolean (*exists)(void);
+};
+
+static gboolean firefox_exists (void);
+static gboolean chrome_exists (void);
+static gboolean chromium_exists (void);
+
+static struct import_option import_options[] = {
+ { N_("GVDB File"), IMPORT_TYPE_CHOOSE, NULL },
+ { N_("HTML File"), IMPORT_TYPE_CHOOSE, NULL },
+ { N_("Firefox"), IMPORT_TYPE_IMPORT, firefox_exists },
+ { N_("Chrome"), IMPORT_TYPE_IMPORT, chrome_exists },
+ { N_("Chromium"), IMPORT_TYPE_IMPORT, chromium_exists }
};
static void
@@ -109,9 +127,9 @@ combo_box_changed_cb (GtkComboBox *combo_box,
g_assert (GTK_IS_BUTTON (button));
active = gtk_combo_box_get_active (combo_box);
- if (active == 0 || active == 1)
+ if (import_options[active].type == IMPORT_TYPE_CHOOSE)
gtk_button_set_label (button, _("Ch_oose File"));
- else if (active == 2)
+ else if (import_options[active].type == IMPORT_TYPE_IMPORT)
gtk_button_set_label (button, _("I_mport"));
}
@@ -182,6 +200,39 @@ get_firefox_profiles (void)
return profiles;
}
+static gboolean
+firefox_exists (void)
+{
+ GSList *firefox_profiles;
+ gboolean has_firefox_profile;
+
+ firefox_profiles = get_firefox_profiles ();
+ has_firefox_profile = g_slist_length (firefox_profiles) > 0;
+ g_slist_free (firefox_profiles);
+
+ return has_firefox_profile;
+}
+
+static gboolean
+chrome_exists (void)
+{
+ g_autofree char *filename = NULL;
+
+ filename = g_build_filename (g_get_user_config_dir (), "google-chrome", "Default", "Bookmarks", NULL);
+
+ return g_file_test (filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR);
+}
+
+static gboolean
+chromium_exists (void)
+{
+ g_autofree char *filename = NULL;
+
+ filename = g_build_filename (g_get_user_config_dir (), "chromium", "Default", "Bookmarks", NULL);
+
+ return g_file_test (filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR);
+}
+
static GtkTreeModel *
create_tree_model (void)
{
@@ -190,27 +241,16 @@ create_tree_model (void)
};
GtkListStore *list_store;
GtkTreeIter iter;
- GSList *firefox_profiles;
- gboolean has_firefox_profile;
int i;
-
- /* Check if user has a firefox profile*/
- firefox_profiles = get_firefox_profiles ();
- has_firefox_profile = g_slist_length (firefox_profiles) > 0;
- g_slist_free (firefox_profiles);
-
list_store = gtk_list_store_new (1, G_TYPE_STRING);
- for (i = G_N_ELEMENTS (import_option_names) - 1; i >= 0; i--) {
- /* Skip Firefox option if user doesn't have a Firefox profile */
- if (g_strcmp0 (import_option_names[i], _("Firefox")) == 0) {
- if (!has_firefox_profile)
- continue;
- }
+ for (i = G_N_ELEMENTS (import_options) - 1; i >= 0; i--) {
+ if (import_options[i].exists && !import_options[i].exists ())
+ continue;
gtk_list_store_prepend (list_store, &iter);
gtk_list_store_set (list_store, &iter,
- TEXT_COL, _(import_option_names[i]),
+ TEXT_COL, _(import_options[i].name),
-1);
}
@@ -410,6 +450,56 @@ dialog_bookmarks_import_from_firefox (GtkDialog *dialog)
return imported;
}
+static gboolean
+dialog_bookmarks_import_from_chrome (GtkDialog *dialog)
+{
+ EphyBookmarksManager *manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
+ GtkWidget *import_info_dialog;
+ g_autoptr (GError) error = NULL;
+ g_autofree gchar *filename;
+ gboolean imported;
+
+ filename = g_build_filename (g_get_user_config_dir (), "google-chrome", "Default", "Bookmarks", NULL);
+
+ imported = ephy_bookmarks_import_from_chrome (manager, filename, &error);
+ import_info_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
+ GTK_DIALOG_MODAL,
+ imported ? GTK_MESSAGE_INFO : GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK,
+ "%s",
+ imported ? _("Bookmarks successfully imported!")
+ : error->message);
+ gtk_dialog_run (GTK_DIALOG (import_info_dialog));
+ gtk_widget_destroy (import_info_dialog);
+
+ return imported;
+}
+
+static gboolean
+dialog_bookmarks_import_from_chromium (GtkDialog *dialog)
+{
+ EphyBookmarksManager *manager = ephy_shell_get_bookmarks_manager (ephy_shell_get_default ());
+ GtkWidget *import_info_dialog;
+ g_autoptr (GError) error = NULL;
+ g_autofree gchar *filename;
+ gboolean imported;
+
+ filename = g_build_filename (g_get_user_config_dir (), "chromium", "Default", "Bookmarks", NULL);
+
+ imported = ephy_bookmarks_import_from_chrome (manager, filename, &error);
+ import_info_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
+ GTK_DIALOG_MODAL,
+ imported ? GTK_MESSAGE_INFO : GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_OK,
+ "%s",
+ imported ? _("Bookmarks successfully imported!")
+ : error->message);
+ gtk_dialog_run (GTK_DIALOG (import_info_dialog));
+ gtk_widget_destroy (import_info_dialog);
+
+ return imported;
+}
+
static void
dialog_bookmarks_import_cb (GtkDialog *dialog,
int response,
@@ -430,6 +520,12 @@ dialog_bookmarks_import_cb (GtkDialog *dialog,
case 2:
imported = dialog_bookmarks_import_from_firefox (dialog);
break;
+ case 3:
+ imported = dialog_bookmarks_import_from_chrome (dialog);
+ break;
+ case 4:
+ imported = dialog_bookmarks_import_from_chromium (dialog);
+ break;
default:
g_assert_not_reached ();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]