[epiphany] Move adblocker filter updating to new EphyFiltersManager class
- From: Michael Catanzaro <mcatanzaro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany] Move adblocker filter updating to new EphyFiltersManager class
- Date: Mon, 23 Jan 2017 05:56:57 +0000 (UTC)
commit 9c23cd821d869a36dc2b9bf3b3ebef5d8cc6830a
Author: Michael Catanzaro <mcatanzaro gnome org>
Date: Sun Jan 22 23:55:57 2017 -0600
Move adblocker filter updating to new EphyFiltersManager class
There is now way too much adblock code in EphyEmbedShell. Move it to a
new file.
embed/ephy-embed-shell.c | 399 ++++++++------------------------------------
lib/Makefile.am | 2 +
lib/ephy-filters-manager.c | 388 ++++++++++++++++++++++++++++++++++++++++++
lib/ephy-filters-manager.h | 34 ++++
4 files changed, 495 insertions(+), 328 deletions(-)
---
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index 8e2cfcc..101caf9 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -30,6 +30,7 @@
#include "ephy-embed-utils.h"
#include "ephy-encodings.h"
#include "ephy-file-helpers.h"
+#include "ephy-filters-manager.h"
#include "ephy-history-service.h"
#include "ephy-profile-utils.h"
#include "ephy-settings.h"
@@ -51,8 +52,6 @@
#define PRINT_SETTINGS_FILENAME "print-settings.ini"
#define OVERVIEW_RELOAD_DELAY 500
-#define ADBLOCK_FILTER_UPDATE_FREQUENCY 24 * 60 * 60 /* In seconds */
-
typedef struct {
WebKitWebContext *web_context;
EphyHistoryService *global_history_service;
@@ -69,9 +68,8 @@ typedef struct {
guint hiding_overview_item;
GDBusServer *dbus_server;
GList *web_extensions;
-
- char *adblock_data_dir;
- GCancellable *uri_tester_update_cancellable;
+ EphyFiltersManager *filters_manager;
+ GCancellable *cancellable;
} EphyEmbedShellPrivate;
enum {
@@ -104,9 +102,9 @@ ephy_embed_shell_dispose (GObject *object)
{
EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (EPHY_EMBED_SHELL (object));
- if (priv->uri_tester_update_cancellable) {
- g_cancellable_cancel (priv->uri_tester_update_cancellable);
- g_clear_object (&priv->uri_tester_update_cancellable);
+ if (priv->cancellable) {
+ g_cancellable_cancel (priv->cancellable);
+ g_clear_object (&priv->cancellable);
}
if (priv->update_overview_timeout_id > 0) {
@@ -125,21 +123,12 @@ ephy_embed_shell_dispose (GObject *object)
g_clear_object (&priv->hosts_manager);
g_clear_object (&priv->web_context);
g_clear_object (&priv->dbus_server);
+ g_clear_object (&priv->filters_manager);
G_OBJECT_CLASS (ephy_embed_shell_parent_class)->dispose (object);
}
static void
-ephy_embed_shell_finalize (GObject *object)
-{
- EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (EPHY_EMBED_SHELL (object));
-
- g_free (priv->adblock_data_dir);
-
- G_OBJECT_CLASS (ephy_embed_shell_parent_class)->finalize (object);
-}
-
-static void
web_extension_form_auth_data_message_received_cb (WebKitUserContentManager *manager,
WebKitJavascriptResult *message,
EphyEmbedShell *shell)
@@ -636,307 +625,6 @@ ftp_request_cb (WebKitURISchemeRequest *request)
g_object_unref (app_info);
}
-#ifdef HAVE_LIBHTTPSEVERYWHERE
-static void
-https_everywhere_update_cb (HTTPSEverywhereUpdater *updater,
- GAsyncResult *result)
-{
- GError *error = NULL;
-
- https_everywhere_updater_update_finish (updater, result, &error);
-
- if (!error)
- return;
-
- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
- !g_error_matches (error, HTTPS_EVERYWHERE_UPDATE_ERROR, HTTPS_EVERYWHERE_UPDATE_ERROR_IN_PROGRESS) &&
- !g_error_matches (error, HTTPS_EVERYWHERE_UPDATE_ERROR,
HTTPS_EVERYWHERE_UPDATE_ERROR_NO_UPDATE_AVAILABLE))
- g_warning ("Failed to update HTTPS Everywhere rulesets: %s", error->message);
- g_error_free (error);
-}
-#endif
-
-static const char *
-ephy_embed_shell_ensure_adblock_data_dir (EphyEmbedShell *shell)
-{
- EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
-
- if (priv->adblock_data_dir)
- return priv->adblock_data_dir;
-
- if (priv->mode == EPHY_EMBED_SHELL_MODE_APPLICATION) {
- char *default_dot_dir = ephy_default_dot_dir ();
-
- priv->adblock_data_dir = g_build_filename (default_dot_dir, "adblock", NULL);
- g_free (default_dot_dir);
- } else
- priv->adblock_data_dir = g_build_filename (ephy_dot_dir (), "adblock", NULL);
- g_mkdir_with_parents (priv->adblock_data_dir, 0700);
-
- return priv->adblock_data_dir;
-}
-
-static gboolean
-adblock_filter_file_is_valid (GFile *file)
-{
- GFileInfo *file_info;
- gboolean result = FALSE;
-
- /* Now check if the local file is too old. */
- file_info = g_file_query_info (file,
- G_FILE_ATTRIBUTE_TIME_MODIFIED","G_FILE_ATTRIBUTE_STANDARD_SIZE,
- G_FILE_QUERY_INFO_NONE,
- NULL,
- NULL);
- if (file_info) {
- if (g_file_info_get_size (file_info) > 0) {
- GTimeVal current_time;
- GTimeVal mod_time;
-
- g_get_current_time (¤t_time);
- g_file_info_get_modification_time (file_info, &mod_time);
-
- if (current_time.tv_sec > mod_time.tv_sec) {
- gint64 expire_time = mod_time.tv_sec + ADBLOCK_FILTER_UPDATE_FREQUENCY;
-
- result = current_time.tv_sec < expire_time;
- }
- }
- g_object_unref (file_info);
- }
-
- return result;
-}
-
-typedef struct {
- EphyEmbedShell *shell;
-
- GFile *src_file;
- GFile *filter_file;
- GFile *tmp_file;
-} AdblockFilterRetrieveData;
-
-static AdblockFilterRetrieveData *
-adblock_filter_retrieve_data_new (EphyEmbedShell *shell,
- GFile *src_file,
- GFile *filter_file)
-{
- AdblockFilterRetrieveData* data;
- char *path, *tmp_path;
-
- data = g_slice_new (AdblockFilterRetrieveData);
- data->shell = g_object_ref (shell);
- data->src_file = g_object_ref (src_file);
- data->filter_file = g_object_ref (filter_file);
-
- path = g_file_get_path (filter_file);
- tmp_path = g_strdup_printf ("%s.tmp", path);
- g_free (path);
- data->tmp_file = g_file_new_for_path (tmp_path);
- g_free (tmp_path);
-
- return data;
-}
-
-static void
-adblock_filter_retrieve_data_free (AdblockFilterRetrieveData *data)
-{
- g_object_unref (data->shell);
- g_object_unref (data->src_file);
- g_object_unref (data->filter_file);
- g_object_unref (data->tmp_file);
-
- g_slice_free (AdblockFilterRetrieveData, data);
-}
-
-static void
-ephy_embed_shell_retrieve_filter_file_finished (GFile *src,
- GAsyncResult *result,
- AdblockFilterRetrieveData *data)
-{
- GError *error = NULL;
-
- if (!g_file_copy_finish (src, result, &error) ||
- !g_file_move (data->tmp_file, data->filter_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error)) {
- GFileOutputStream *stream;
-
- /* If failed to retrieve, create an empty file if it doesn't exist to unblock extensions */
- stream = g_file_create (data->filter_file, G_FILE_CREATE_NONE, NULL, NULL);
- if (stream)
- g_object_unref (stream);
-
- if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
- g_warning ("Error retrieving filter %s: %s\n", g_file_get_uri (data->src_file), error->message);
- g_error_free (error);
- }
-
- adblock_filter_retrieve_data_free (data);
-}
-
-static void
-ephy_embed_shell_retrieve_filter_file (EphyEmbedShell *shell,
- const char *filter_url,
- GFile *file)
-{
- EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
- GFile *src = g_file_new_for_uri (filter_url);
- AdblockFilterRetrieveData *data;
-
- if (!priv->uri_tester_update_cancellable)
- priv->uri_tester_update_cancellable = g_cancellable_new ();
-
- data = adblock_filter_retrieve_data_new (shell, src, file);
-
- g_file_copy_async (src, data->tmp_file,
- G_FILE_COPY_OVERWRITE,
- G_PRIORITY_DEFAULT,
- priv->uri_tester_update_cancellable,
- NULL, NULL,
- (GAsyncReadyCallback)ephy_embed_shell_retrieve_filter_file_finished,
- data);
-
- g_object_unref (src);
-}
-
-static void
-ephy_embed_shell_remove_old_adblock_filters (EphyEmbedShell *shell,
- GList *current_files)
-{
- EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
- GFile *file;
- GFile *filters_dir;
- GFileEnumerator *enumerator;
- gboolean current_filter;
- GError *error = NULL;
-
- filters_dir = g_file_new_for_path (ephy_embed_shell_ensure_adblock_data_dir (shell));
- enumerator = g_file_enumerate_children (filters_dir,
- G_FILE_ATTRIBUTE_STANDARD_NAME,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL,
- &error);
- if (error != NULL) {
- g_warning ("Failed to enumerate children of %s: %s", priv->adblock_data_dir, error->message);
- g_error_free (error);
- g_object_unref (filters_dir);
- return;
- }
-
- /* For each file in the adblock directory, check if it is a currently-enabled
- * and remove it if not, since filter files can be quite large. */
- for (;;) {
- g_file_enumerator_iterate (enumerator, NULL, &file, NULL, &error);
- if (error != NULL) {
- g_warning ("Failed to iterate file enumerator for %s: %s", priv->adblock_data_dir, error->message);
- g_clear_error (&error);
- continue;
- }
-
- /* Success: no more files left to iterate. */
- if (file == NULL)
- break;
-
- current_filter = FALSE;
- for (GList *l = current_files; l != NULL; l = l->next) {
- if (g_file_equal (l->data, file)) {
- current_filter = TRUE;
- break;
- }
- }
-
- if (!current_filter) {
- g_file_delete (file, NULL, &error);
- if (error != NULL) {
- g_warning ("Failed to remove %s: %s", g_file_get_path (file), error->message);
- g_clear_error (&error);
- }
- }
- }
-
- g_object_unref (filters_dir);
- g_object_unref (enumerator);
-}
-
-static void
-ephy_embed_shell_update_adblock_filter_files (EphyEmbedShell *shell)
-{
- EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
- char **filters;
- GList *files = NULL;
-
- /* One at a time please! */
- if (priv->uri_tester_update_cancellable)
- g_cancellable_cancel (priv->uri_tester_update_cancellable);
-
- if (!g_settings_get_boolean (EPHY_SETTINGS_WEB, EPHY_PREFS_WEB_ENABLE_ADBLOCK)) {
- ephy_embed_shell_remove_old_adblock_filters (shell, files);
- return;
- }
-
- filters = g_settings_get_strv (EPHY_SETTINGS_WEB, EPHY_PREFS_WEB_ADBLOCK_FILTERS);
- for (guint i = 0; filters[i]; i++) {
- GFile *filter_file;
-
- filter_file = ephy_uri_tester_get_adblock_filter_file (ephy_embed_shell_ensure_adblock_data_dir (shell),
filters[i]);
- if (!adblock_filter_file_is_valid (filter_file))
- ephy_embed_shell_retrieve_filter_file (shell, filters[i], filter_file);
- files = g_list_prepend (files, filter_file);
- }
-
- ephy_embed_shell_remove_old_adblock_filters (shell, files);
-
- g_strfreev (filters);
- g_list_free_full (files, g_object_unref);
-}
-
-static void
-ephy_uri_tester_adblock_filters_changed_cb (GSettings *settings,
- char *key,
- EphyEmbedShell *shell)
-{
- ephy_embed_shell_update_adblock_filter_files (shell);
-}
-
-static void
-ephy_uri_tester_enable_adblock_changed_cb (GSettings *settings,
- char *key,
- EphyEmbedShell *shell)
-{
- ephy_embed_shell_update_adblock_filter_files (shell);
-}
-
-static void
-ephy_embed_shell_update_uri_tester (EphyEmbedShell *shell)
-{
- EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
-
- ephy_embed_shell_update_adblock_filter_files (shell);
-
- if (priv->mode != EPHY_EMBED_SHELL_MODE_TEST &&
- priv->mode != EPHY_EMBED_SHELL_MODE_SEARCH_PROVIDER) {
-#ifdef HAVE_LIBHTTPSEVERYWHERE
- HTTPSEverywhereContext *context;
- HTTPSEverywhereUpdater *updater;
-#endif
-
- if (!priv->uri_tester_update_cancellable)
- priv->uri_tester_update_cancellable = g_cancellable_new ();
-
-#ifdef HAVE_LIBHTTPSEVERYWHERE
- /* We might want to be smarter about this in the future. For now,
- * trigger an update of the rulesets once each time Epiphany is started. */
- context = https_everywhere_context_new ();
- updater = https_everywhere_updater_new (context);
- https_everywhere_updater_update (updater,
- priv->uri_tester_update_cancellable,
- (GAsyncReadyCallback)https_everywhere_update_cb,
- NULL);
- g_object_unref (context);
- g_object_unref (updater);
-#endif
- }
-}
-
static void
web_extension_destroyed (EphyEmbedShell *shell,
GObject *web_extension)
@@ -980,7 +668,7 @@ initialize_web_extensions (WebKitWebContext *web_context,
user_data = g_variant_new ("(msssb)",
address,
ephy_dot_dir (),
- ephy_embed_shell_ensure_adblock_data_dir (shell),
+ ephy_filters_manager_get_adblock_filters_dir (priv->filters_manager),
private_profile);
webkit_web_context_set_web_extensions_initialization_user_data (web_context, user_data);
}
@@ -1116,6 +804,43 @@ ephy_embed_shell_create_web_context (EphyEmbedShell *shell)
g_object_unref (manager);
}
+#ifdef HAVE_LIBHTTPSEVERYWHERE
+static void
+https_everywhere_update_cb (HTTPSEverywhereUpdater *updater,
+ GAsyncResult *result)
+{
+ GError *error = NULL;
+
+ https_everywhere_updater_update_finish (updater, result, &error);
+
+ if (!error)
+ return;
+
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
+ !g_error_matches (error, HTTPS_EVERYWHERE_UPDATE_ERROR, HTTPS_EVERYWHERE_UPDATE_ERROR_IN_PROGRESS) &&
+ !g_error_matches (error, HTTPS_EVERYWHERE_UPDATE_ERROR,
HTTPS_EVERYWHERE_UPDATE_ERROR_NO_UPDATE_AVAILABLE))
+ g_warning ("Failed to update HTTPS Everywhere rulesets: %s", error->message);
+ g_error_free (error);
+}
+#endif
+
+static char *
+adblock_filters_dir (EphyEmbedShell *shell)
+{
+ EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
+ char *result;
+
+ if (priv->mode == EPHY_EMBED_SHELL_MODE_APPLICATION) {
+ char *default_dot_dir = ephy_default_dot_dir ();
+
+ result = g_build_filename (default_dot_dir, "adblock", NULL);
+ g_free (default_dot_dir);
+ } else
+ result = g_build_filename (ephy_dot_dir (), "adblock", NULL);
+
+ return result;
+}
+
static void
ephy_embed_shell_startup (GApplication *application)
{
@@ -1125,16 +850,17 @@ ephy_embed_shell_startup (GApplication *application)
WebKitCookieManager *cookie_manager;
char *filename;
char *cookie_policy;
+ char *filters_dir;
+#ifdef HAVE_LIBHTTPSEVERYWHERE
+ HTTPSEverywhereContext *context;
+ HTTPSEverywhereUpdater *updater;
+#endif
G_APPLICATION_CLASS (ephy_embed_shell_parent_class)->startup (application);
- /* Note: up here because we must connect *before* reading the settings. */
- g_signal_connect (EPHY_SETTINGS_WEB, "changed::" EPHY_PREFS_WEB_ADBLOCK_FILTERS,
- G_CALLBACK (ephy_uri_tester_adblock_filters_changed_cb), shell);
- g_signal_connect (EPHY_SETTINGS_WEB, "changed::" EPHY_PREFS_WEB_ENABLE_ADBLOCK,
- G_CALLBACK (ephy_uri_tester_enable_adblock_changed_cb), shell);
-
- ephy_embed_shell_update_uri_tester (shell);
+ filters_dir = adblock_filters_dir (shell);
+ priv->filters_manager = ephy_filters_manager_new (filters_dir);
+ g_free (filters_dir);
ephy_embed_shell_create_web_context (shell);
@@ -1228,6 +954,24 @@ ephy_embed_shell_startup (GApplication *application)
EPHY_PREFS_WEB_COOKIES_POLICY);
ephy_embed_prefs_set_cookie_accept_policy (cookie_manager, cookie_policy);
g_free (cookie_policy);
+
+#ifdef HAVE_LIBHTTPSEVERYWHERE
+ /* We might want to be smarter about this in the future. For now,
+ * trigger an update of the rulesets once each time Epiphany is started.
+ * Note that the updated rules will not be used until the next time Epiphany
+ * is started. */
+ if (priv->mode != EPHY_EMBED_SHELL_MODE_TEST &&
+ priv->mode != EPHY_EMBED_SHELL_MODE_SEARCH_PROVIDER) {
+ context = https_everywhere_context_new ();
+ updater = https_everywhere_updater_new (context);
+ https_everywhere_updater_update (updater,
+ priv->cancellable,
+ (GAsyncReadyCallback)https_everywhere_update_cb,
+ NULL);
+ g_object_unref (context);
+ g_object_unref (updater);
+ }
+#endif
}
static void
@@ -1326,7 +1070,6 @@ ephy_embed_shell_class_init (EphyEmbedShellClass *klass)
GApplicationClass *application_class = G_APPLICATION_CLASS (klass);
object_class->dispose = ephy_embed_shell_dispose;
- object_class->finalize = ephy_embed_shell_finalize;
object_class->set_property = ephy_embed_shell_set_property;
object_class->get_property = ephy_embed_shell_get_property;
object_class->constructed = ephy_embed_shell_constructed;
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 43a25f2..784dc1c 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -17,6 +17,8 @@ libephymisc_la_SOURCES = \
ephy-favicon-helpers.h \
ephy-file-helpers.c \
ephy-file-helpers.h \
+ ephy-filters-manager.c \
+ ephy-filters-manager.h \
ephy-form-auth-data.c \
ephy-form-auth-data.h \
ephy-gui.c \
diff --git a/lib/ephy-filters-manager.c b/lib/ephy-filters-manager.c
new file mode 100644
index 0000000..04504e1
--- /dev/null
+++ b/lib/ephy-filters-manager.c
@@ -0,0 +1,388 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/*
+ * Copyright © 2017 Igalia S.L.
+ *
+ * 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-filters-manager.h"
+
+#include "ephy-prefs.h"
+#include "ephy-settings.h"
+#include "ephy-uri-tester-shared.h"
+
+#include <gio/gio.h>
+
+#define ADBLOCK_FILTER_UPDATE_FREQUENCY 24 * 60 * 60 /* In seconds */
+
+struct _EphyFiltersManager {
+ GObject parent_instance;
+
+ char *filters_dir;
+ GCancellable *cancellable;
+};
+
+G_DEFINE_TYPE (EphyFiltersManager, ephy_filters_manager, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_FILTERS_DIR,
+ N_PROPERTIES
+};
+
+static GParamSpec *object_properties[N_PROPERTIES] = { NULL, };
+
+static gboolean
+adblock_filter_file_is_valid (GFile *file)
+{
+ GFileInfo *file_info;
+ gboolean result = FALSE;
+
+ /* Now check if the local file is too old. */
+ file_info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_TIME_MODIFIED","G_FILE_ATTRIBUTE_STANDARD_SIZE,
+ G_FILE_QUERY_INFO_NONE,
+ NULL,
+ NULL);
+ if (file_info) {
+ if (g_file_info_get_size (file_info) > 0) {
+ GTimeVal current_time;
+ GTimeVal mod_time;
+
+ g_get_current_time (¤t_time);
+ g_file_info_get_modification_time (file_info, &mod_time);
+
+ if (current_time.tv_sec > mod_time.tv_sec) {
+ gint64 expire_time = mod_time.tv_sec + ADBLOCK_FILTER_UPDATE_FREQUENCY;
+
+ result = current_time.tv_sec < expire_time;
+ }
+ }
+ g_object_unref (file_info);
+ }
+
+ return result;
+}
+
+typedef struct {
+ EphyFiltersManager *manager;
+
+ GFile *src_file;
+ GFile *filter_file;
+ GFile *tmp_file;
+} AdblockFilterRetrieveData;
+
+static AdblockFilterRetrieveData *
+adblock_filter_retrieve_data_new (EphyFiltersManager *manager,
+ GFile *src_file,
+ GFile *filter_file)
+{
+ AdblockFilterRetrieveData* data;
+ char *path, *tmp_path;
+
+ data = g_slice_new (AdblockFilterRetrieveData);
+ data->manager = g_object_ref (manager);
+ data->src_file = g_object_ref (src_file);
+ data->filter_file = g_object_ref (filter_file);
+
+ path = g_file_get_path (filter_file);
+ tmp_path = g_strdup_printf ("%s.tmp", path);
+ g_free (path);
+ data->tmp_file = g_file_new_for_path (tmp_path);
+ g_free (tmp_path);
+
+ return data;
+}
+
+static void
+adblock_filter_retrieve_data_free (AdblockFilterRetrieveData *data)
+{
+ g_object_unref (data->manager);
+ g_object_unref (data->src_file);
+ g_object_unref (data->filter_file);
+ g_object_unref (data->tmp_file);
+
+ g_slice_free (AdblockFilterRetrieveData, data);
+}
+
+static void
+retrieve_filter_file_finished (GFile *src,
+ GAsyncResult *result,
+ AdblockFilterRetrieveData *data)
+{
+ GError *error = NULL;
+
+ if (!g_file_copy_finish (src, result, &error) ||
+ !g_file_move (data->tmp_file, data->filter_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error)) {
+ GFileOutputStream *stream;
+
+ /* If failed to retrieve, create an empty file if it doesn't exist to unblock extensions */
+ stream = g_file_create (data->filter_file, G_FILE_CREATE_NONE, NULL, NULL);
+ if (stream)
+ g_object_unref (stream);
+
+ if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ g_warning ("Error retrieving filter %s: %s\n", g_file_get_uri (data->src_file), error->message);
+ g_error_free (error);
+ }
+
+ adblock_filter_retrieve_data_free (data);
+}
+
+static void
+retrieve_filter_file (EphyFiltersManager *manager,
+ const char *filter_url,
+ GFile *file)
+{
+ GFile *src = g_file_new_for_uri (filter_url);
+ AdblockFilterRetrieveData *data;
+
+ data = adblock_filter_retrieve_data_new (manager, src, file);
+
+ g_file_copy_async (src, data->tmp_file,
+ G_FILE_COPY_OVERWRITE,
+ G_PRIORITY_DEFAULT,
+ manager->cancellable,
+ NULL, NULL,
+ (GAsyncReadyCallback)retrieve_filter_file_finished,
+ data);
+
+ g_object_unref (src);
+}
+
+static void
+remove_old_adblock_filters (EphyFiltersManager *manager,
+ GList *current_files)
+{
+ GFile *file;
+ GFile *filters_dir;
+ GFileEnumerator *enumerator;
+ gboolean current_filter;
+ GError *error = NULL;
+
+ filters_dir = g_file_new_for_path (manager->filters_dir);
+ enumerator = g_file_enumerate_children (filters_dir,
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL,
+ &error);
+ if (error != NULL) {
+ g_warning ("Failed to enumerate children of %s: %s", manager->filters_dir, error->message);
+ g_error_free (error);
+ g_object_unref (filters_dir);
+ return;
+ }
+
+ /* For each file in the adblock directory, check if it is a currently-enabled
+ * and remove it if not, since filter files can be quite large. */
+ for (;;) {
+ g_file_enumerator_iterate (enumerator, NULL, &file, NULL, &error);
+ if (error != NULL) {
+ g_warning ("Failed to iterate file enumerator for %s: %s", manager->filters_dir, error->message);
+ g_clear_error (&error);
+ continue;
+ }
+
+ /* Success: no more files left to iterate. */
+ if (file == NULL)
+ break;
+
+ current_filter = FALSE;
+ for (GList *l = current_files; l != NULL; l = l->next) {
+ if (g_file_equal (l->data, file)) {
+ current_filter = TRUE;
+ break;
+ }
+ }
+
+ if (!current_filter) {
+ g_file_delete (file, NULL, &error);
+ if (error != NULL) {
+ g_warning ("Failed to remove %s: %s", g_file_get_path (file), error->message);
+ g_clear_error (&error);
+ }
+ }
+ }
+
+ g_object_unref (filters_dir);
+ g_object_unref (enumerator);
+}
+
+static void
+update_adblock_filter_files (EphyFiltersManager *manager)
+{
+ char **filters;
+ GList *files = NULL;
+
+ /* One at a time please! */
+ if (manager->cancellable)
+ g_cancellable_cancel (manager->cancellable);
+ else
+ manager->cancellable = g_cancellable_new ();
+
+ if (!g_settings_get_boolean (EPHY_SETTINGS_WEB, EPHY_PREFS_WEB_ENABLE_ADBLOCK)) {
+ remove_old_adblock_filters (manager, files);
+ return;
+ }
+
+ filters = g_settings_get_strv (EPHY_SETTINGS_WEB, EPHY_PREFS_WEB_ADBLOCK_FILTERS);
+ for (guint i = 0; filters[i]; i++) {
+ GFile *filter_file;
+
+ filter_file = ephy_uri_tester_get_adblock_filter_file (manager->filters_dir, filters[i]);
+ if (!adblock_filter_file_is_valid (filter_file))
+ retrieve_filter_file (manager, filters[i], filter_file);
+ files = g_list_prepend (files, filter_file);
+ }
+
+ remove_old_adblock_filters (manager, files);
+
+ g_strfreev (filters);
+ g_list_free_full (files, g_object_unref);
+}
+
+static void
+adblock_filters_changed_cb (GSettings *settings,
+ char *key,
+ EphyFiltersManager *manager)
+{
+ update_adblock_filter_files (manager);
+}
+
+static void
+enable_adblock_changed_cb (GSettings *settings,
+ char *key,
+ EphyFiltersManager *manager)
+{
+ update_adblock_filter_files (manager);
+}
+
+static void
+ephy_filters_manager_dispose (GObject *object)
+{
+ EphyFiltersManager *manager = EPHY_FILTERS_MANAGER (object);
+
+ if (manager->cancellable) {
+ g_cancellable_cancel (manager->cancellable);
+ g_clear_object (&manager->cancellable);
+ }
+
+ G_OBJECT_CLASS (ephy_filters_manager_parent_class)->dispose (object);
+}
+
+static void
+ephy_filters_manager_finalize (GObject *object)
+{
+ EphyFiltersManager *manager = EPHY_FILTERS_MANAGER (object);
+
+ g_free (manager->filters_dir);
+
+ G_OBJECT_CLASS (ephy_filters_manager_parent_class)->finalize (object);
+}
+
+static void
+ephy_filters_manager_constructed (GObject *object)
+{
+ EphyFiltersManager *manager = EPHY_FILTERS_MANAGER (object);
+
+ G_OBJECT_CLASS (ephy_filters_manager_parent_class)->constructed (object);
+
+ /* Note: up here because we must connect *before* reading the settings. */
+ g_signal_connect (EPHY_SETTINGS_WEB, "changed::" EPHY_PREFS_WEB_ADBLOCK_FILTERS,
+ G_CALLBACK (adblock_filters_changed_cb), manager);
+ g_signal_connect (EPHY_SETTINGS_WEB, "changed::" EPHY_PREFS_WEB_ENABLE_ADBLOCK,
+ G_CALLBACK (enable_adblock_changed_cb), manager);
+
+ g_mkdir_with_parents (manager->filters_dir, 0700);
+ update_adblock_filter_files (manager);
+}
+
+static void
+ephy_filters_manager_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyFiltersManager *manager = EPHY_FILTERS_MANAGER (object);
+
+ switch (prop_id) {
+ case PROP_FILTERS_DIR:
+ manager->filters_dir = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_filters_manager_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyFiltersManager *manager = EPHY_FILTERS_MANAGER (object);
+
+ switch (prop_id) {
+ case PROP_FILTERS_DIR:
+ g_value_set_string (value, manager->filters_dir);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_filters_manager_class_init (EphyFiltersManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructed = ephy_filters_manager_constructed;
+ object_class->dispose = ephy_filters_manager_dispose;
+ object_class->finalize = ephy_filters_manager_finalize;
+ object_class->set_property = ephy_filters_manager_set_property;
+ object_class->get_property = ephy_filters_manager_get_property;
+
+ object_properties[PROP_FILTERS_DIR] =
+ g_param_spec_string ("filters-dir",
+ "Filters directory",
+ "The directory in which adblock filters are saved",
+ "",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class,
+ N_PROPERTIES,
+ object_properties);
+}
+
+static void
+ephy_filters_manager_init (EphyFiltersManager *manager)
+{
+}
+
+EphyFiltersManager *
+ephy_filters_manager_new (const char *filters_dir)
+{
+ return EPHY_FILTERS_MANAGER (g_object_new (EPHY_TYPE_FILTERS_MANAGER,
+ "filters-dir", filters_dir,
+ NULL));
+}
+
+const char *
+ephy_filters_manager_get_adblock_filters_dir (EphyFiltersManager *manager)
+{
+ return manager->filters_dir;
+}
diff --git a/lib/ephy-filters-manager.h b/lib/ephy-filters-manager.h
new file mode 100644
index 0000000..38fb53c
--- /dev/null
+++ b/lib/ephy-filters-manager.h
@@ -0,0 +1,34 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/*
+ * Copyright © 2017 Igalia S.L.
+ *
+ * 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>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_FILTERS_MANAGER (ephy_filters_manager_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyFiltersManager, ephy_filters_manager, EPHY, FILTERS_MANAGER, GObject)
+
+EphyFiltersManager *ephy_filters_manager_new (const char *adblock_filters_dir);
+const char *ephy_filters_manager_get_adblock_filters_dir (EphyFiltersManager *manager);
+
+G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]