[epiphany-extensions] adblock: Add the new 'Ad Blocker' extension, namely 'Ad Blocker v2'.



commit f9fb2ae8787193eefa6d96fbe5769551cf99041b
Author: Mario Sanchez Prada <msanchez igalia com>
Date:   Sat Dec 3 20:58:58 2011 +0100

    adblock: Add the new 'Ad Blocker' extension, namely 'Ad Blocker v2'.
    
    Based on Midori's adblocker, this new version of the extension has been
    written to be as simple as possible and compatible with the EasyList
    subscriptions for 'AdBlock Plus' (http://easylist.adblockplus.org).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=660154

 configure.ac                                    |    9 +-
 extensions/adblock/Makefile.am                  |   47 ++
 extensions/adblock/adblock-ui.c                 |  388 +++++++++++
 extensions/adblock/adblock-ui.h                 |   62 ++
 extensions/adblock/adblock.ephy-extension.in.in |   10 +
 extensions/adblock/adblock.ui                   |  198 ++++++
 extensions/adblock/ephy-adblock-extension.c     |  317 +++++++++
 extensions/adblock/ephy-adblock-extension.h     |   58 ++
 extensions/adblock/extension.c                  |   44 ++
 extensions/adblock/uri-tester.c                 |  820 +++++++++++++++++++++++
 extensions/adblock/uri-tester.h                 |   71 ++
 11 files changed, 2020 insertions(+), 4 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index a9f7420..d764e94 100644
--- a/configure.ac
+++ b/configure.ac
@@ -169,9 +169,9 @@ AM_CONDITIONAL([HAVE_OPENSP],[test "x$enable_opensp" = "xyes"])
 
 AC_MSG_CHECKING([which extensions to build])
 
-ALL_EXTENSIONS="actions auto-reload auto-scroller certificates error-viewer extensions-manager-ui gestures greasemonkey html5tube java-console livehttpheaders page-info permissions push-scroller rss sample select-stylesheet smart-bookmarks soup-fly tab-key-tab-navigate tab-states"
-USEFUL_EXTENSIONS="actions auto-reload auto-scroller certificates extensions-manager-ui html5tube java-console page-info push-scroller select-stylesheet smart-bookmarks soup-fly tab-key-tab-navigate tab-states"
-DEFAULT_EXTENSIONS="actions auto-reload certificates extensions-manager-ui greasemonkey gestures html5tube push-scroller soup-fly tab-key-tab-navigate tab-states rss"
+ALL_EXTENSIONS="actions adblock auto-reload auto-scroller certificates error-viewer extensions-manager-ui gestures greasemonkey html5tube java-console livehttpheaders page-info permissions push-scroller rss sample select-stylesheet smart-bookmarks soup-fly tab-key-tab-navigate tab-states"
+USEFUL_EXTENSIONS="actions adblock auto-reload auto-scroller certificates extensions-manager-ui html5tube java-console page-info push-scroller select-stylesheet smart-bookmarks soup-fly tab-key-tab-navigate tab-states"
+DEFAULT_EXTENSIONS="actions adblock auto-reload certificates extensions-manager-ui greasemonkey gestures html5tube push-scroller soup-fly tab-key-tab-navigate tab-states rss"
 
 MOZILLA_ALL_EXTENSIONS="error-viewer java-console livehttpheaders page-info select-stylesheet smart-bookmarks"
 
@@ -184,7 +184,7 @@ DIST_EXTENSIONS="$ALL_EXTENSIONS"
 AC_ARG_WITH([extensions],
 [  --with-extensions=extension1,extension2,...
 			  build the specified extensions. Available:
-			  actions, auto-reload, auto-scroller,
+			  actions, adblock, auto-reload, auto-scroller,
 			  certificates, error-viewer, extensions-manager-ui,
 			  gestures, greasemonkey, java-console, livehttpheaders, page-info,
 			  permissions, push-scroller, rss, sample,
@@ -275,6 +275,7 @@ data/Makefile
 data/icons/Makefile
 extensions/Makefile
 extensions/actions/Makefile
+extensions/adblock/Makefile
 extensions/auto-reload/Makefile
 extensions/auto-scroller/Makefile
 extensions/certificates/Makefile
diff --git a/extensions/adblock/Makefile.am b/extensions/adblock/Makefile.am
new file mode 100644
index 0000000..c6f8c6f
--- /dev/null
+++ b/extensions/adblock/Makefile.am
@@ -0,0 +1,47 @@
+extensiondir = $(EXTENSIONS_DIR)
+extension_LTLIBRARIES = libadblockextension.la
+
+libadblockextension_la_SOURCES = \
+	ephy-adblock-extension.c	\
+	ephy-adblock-extension.h	\
+	uri-tester.h			\
+	uri-tester.c			\
+	adblock-ui.h			\
+	adblock-ui.c			\
+	extension.c
+
+libadblockextension_la_CPPFLAGS = \
+        -I$(top_srcdir)/include				\
+	-DSHARE_DIR=\"$(pkgdatadir)\"			\
+	-DEPHY_EXTENSIONS_LOCALEDIR=\"$(datadir)/locale\"  \
+	-D_GNU_SOURCE					\
+	$(AM_CPPFLAGS)
+
+libadblockextension_la_CFLAGS = \
+	$(EPIPHANY_DEPENDENCY_CFLAGS)	\
+	$(AM_CFLAGS)
+
+libadblockextension_la_LDFLAGS = \
+	-module -avoid-version \
+	-export-symbols $(top_srcdir)/ephy-extension.symbols \
+	$(AM_LDFLAGS)
+
+uidir = $(pkgdatadir)/ui
+ui_DATA = adblock.ui
+
+extensioninidir = $(extensiondir)
+extensionini_in_files = adblock.ephy-extension.in.in
+extensionini_DATA = $(extensionini_in_files:.ephy-extension.in.in=.ephy-extension)
+
+%.ephy-extension.in: %.ephy-extension.in.in $(extension_LTLIBRARIES)
+	$(AM_V_GEN) \
+	sed -e "s|%LIBRARY%|`. ./$(extension_LTLIBRARIES) && echo $$dlname`|" \
+	    -e "s|%EXTENSION_DIR%|$(extensiondir)|" \
+	$< > $@
+
+ EPIPHANY_EXTENSION_RULE@
+
+CLEANFILES = $(extensionini_DATA)
+DISTCLEANFILES = $(extensionini_DATA)
+
+EXTRA_DIST = $(ui_DATA) $(extensionini_in_files)
diff --git a/extensions/adblock/adblock-ui.c b/extensions/adblock/adblock-ui.c
new file mode 100644
index 0000000..db66556
--- /dev/null
+++ b/extensions/adblock/adblock-ui.c
@@ -0,0 +1,388 @@
+/*
+ *  Copyright  2011 Igalia S.L.
+ *
+ *  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.
+ *
+ *  Some parts of this file based on the Midori's 'adblock' extension,
+ *  licensed with the GNU Lesser General Public License 2.1, Copyright
+ *  (C) 2009-2010 Christian Dywan <christian twotoasts de> and 2009
+ *  Alexander Butenko <a butenka gmail com>. Check Midori's web site
+ *  at http://www.twotoasts.de
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "adblock-ui.h"
+
+#include "ephy-debug.h"
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#define ADBLOCK_UI_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE((object), TYPE_ADBLOCK_UI, AdblockUIPrivate))
+
+#define ADBLOCK_FILTER_VALID(__filter)              \
+  (__filter && (g_str_has_prefix (__filter, "http") \
+                || g_str_has_prefix (__filter, "file")))
+
+struct _AdblockUIPrivate
+{
+  GtkWidget *dialog;
+
+  /* The dialog buttons. */
+  GtkEntry *new_filter;
+  GtkButton *add, *edit, *remove;
+
+  /* Data. */
+  GtkTreeView *treeview;
+  GtkTreeSelection *selection;
+  GtkListStore *store;
+
+  /* The uri tester. */
+  UriTester *tester;
+
+  /* Whether something has actually changed. */
+  gboolean dirty;
+};
+
+enum
+{
+  PROP_0,
+  PROP_TESTER,
+};
+
+enum
+{
+  COL_FILTER_URI,
+  N_COLUMNS
+};
+
+G_DEFINE_DYNAMIC_TYPE (AdblockUI, adblock_ui, EPHY_TYPE_DIALOG);
+
+/* Private functions. */
+
+static gboolean
+adblock_ui_foreach_save (GtkTreeModel *model,
+                         GtkTreePath  *path,
+                         GtkTreeIter  *iter,
+                         GSList       **filters)
+{
+  char *filter = NULL;
+
+  gtk_tree_model_get (model, iter, COL_FILTER_URI, &filter, -1);
+  *filters = g_slist_prepend (*filters, filter);
+
+  return FALSE;
+}
+
+static void
+adblock_ui_save (AdblockUI *dialog)
+{
+  GSList *filters = NULL;
+  gtk_tree_model_foreach (GTK_TREE_MODEL (dialog->priv->store),
+                          (GtkTreeModelForeachFunc)adblock_ui_foreach_save,
+                          &filters);
+
+  uri_tester_set_filters (dialog->priv->tester, filters);
+}
+
+static void
+adblock_ui_response_cb (GtkWidget *widget,
+                        int response,
+                        AdblockUI *dialog)
+{
+  if (response == GTK_RESPONSE_CLOSE && dialog->priv->dirty)
+    {
+      EphyAdBlockManager *manager;
+
+      adblock_ui_save (dialog);
+
+      /* Ask uri tester to reload all its patterns. */
+      uri_tester_reload (dialog->priv->tester);
+
+      /* Ask manager to emit a signal that rules have changed. */
+      manager = EPHY_ADBLOCK_MANAGER (ephy_embed_shell_get_adblock_manager (embed_shell));
+
+      g_signal_emit_by_name (manager, "rules_changed", NULL);
+    }
+
+  g_object_unref (dialog);
+}
+
+static void
+adblock_ui_add_filter (AdblockUI *dialog)
+{
+  GtkTreeIter iter;
+
+  const char *new_filter = gtk_entry_get_text (dialog->priv->new_filter);
+
+  if (ADBLOCK_FILTER_VALID (new_filter))
+    {
+      GtkListStore *store = dialog->priv->store;
+
+      gtk_list_store_append (store, &iter);
+      gtk_list_store_set (store, &iter, COL_FILTER_URI, new_filter, -1);
+
+      /* Makes the pattern field blank. */
+      gtk_entry_set_text (dialog->priv->new_filter, "");
+
+      dialog->priv->dirty = TRUE;
+    }
+  else
+    {
+      GtkWidget *error_dialog = NULL;
+      error_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog->priv->dialog),
+                                             GTK_DIALOG_MODAL,
+                                             GTK_MESSAGE_ERROR,
+                                             GTK_BUTTONS_OK,
+                                             "%s",
+                                             _("Invalid filter"));
+      gtk_dialog_run (GTK_DIALOG (error_dialog));
+      gtk_widget_destroy (error_dialog);
+
+      gtk_entry_set_text (dialog->priv->new_filter, "");
+    }
+}
+
+static void
+adblock_ui_add_cb (GtkButton *button,
+                   AdblockUI *dialog)
+{
+  adblock_ui_add_filter (dialog);
+}
+
+static void
+adblock_ui_edit_cb (GtkButton *button,
+                    AdblockUI *dialog)
+{
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  GtkTreeSelection *selection;
+
+  selection = dialog->priv->selection;
+
+  if (gtk_tree_selection_get_selected (selection, &model, &iter))
+    {
+      char* path = gtk_tree_model_get_string_from_iter (model, &iter);
+      GtkTreePath* tree_path = gtk_tree_path_new_from_string (path);
+      GtkTreeView *treeview = dialog->priv->treeview;
+      GtkTreeViewColumn *column = gtk_tree_view_get_column (treeview,
+                                                            COL_FILTER_URI);
+
+      gtk_tree_view_set_cursor (treeview, tree_path, column, TRUE);
+      gtk_tree_path_free (tree_path);
+      g_free (path);
+    }
+}
+
+static void
+adblock_ui_remove_cb (GtkButton *button,
+                      AdblockUI *dialog)
+{
+  GtkTreeModel *model;
+  GtkTreeIter iter;
+  GtkTreeSelection *selection;
+
+  selection = dialog->priv->selection;
+
+  if (gtk_tree_selection_get_selected (selection, &model, &iter))
+    {
+      gtk_list_store_remove (GTK_LIST_STORE(model), &iter);
+      gtk_entry_set_text (dialog->priv->new_filter, "");
+
+      dialog->priv->dirty = TRUE;
+    }
+}
+
+static void
+adblock_ui_cell_edited_cb (GtkCellRendererText *cell,
+                           char               *path_string,
+                           char               *new_filter,
+                           AdblockUI           *dialog)
+{
+  GtkTreeModel *model = GTK_TREE_MODEL (dialog->priv->store);
+  GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
+  GtkTreeIter iter;
+
+  gtk_tree_model_get_iter (model, &iter, path);
+  gtk_list_store_set (dialog->priv->store, &iter, COL_FILTER_URI, new_filter, -1);
+  gtk_tree_path_free (path);
+
+  dialog->priv->dirty = TRUE;
+}
+
+static void
+adblock_ui_build_treeview (AdblockUI *dialog)
+{
+  GtkCellRenderer *renderer;
+
+  dialog->priv->store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING);
+
+  renderer = gtk_cell_renderer_text_new ();
+  g_object_set(renderer, "editable", TRUE, NULL);
+  g_signal_connect(renderer,
+                   "edited",
+                   (GCallback) adblock_ui_cell_edited_cb,
+                   (gpointer)dialog);
+
+  gtk_tree_view_insert_column_with_attributes (dialog->priv->treeview,
+                                               COL_FILTER_URI, _("Filter URI"),
+                                               renderer,
+                                               "text", COL_FILTER_URI,
+                                               NULL);
+
+  gtk_tree_sortable_set_sort_column_id (
+                                        GTK_TREE_SORTABLE (dialog->priv->store),
+                                        COL_FILTER_URI,
+                                        GTK_SORT_ASCENDING);
+
+  gtk_tree_view_set_model (dialog->priv->treeview, GTK_TREE_MODEL (dialog->priv->store));
+  gtk_tree_view_set_search_column (dialog->priv->treeview, COL_FILTER_URI);
+
+  g_object_unref (dialog->priv->store);
+
+  dialog->priv->selection = gtk_tree_view_get_selection (dialog->priv->treeview);
+  gtk_tree_selection_set_mode (dialog->priv->selection, GTK_SELECTION_SINGLE);
+
+  dialog->priv->dirty = FALSE;
+}
+
+static void
+adblock_ui_populate_store (AdblockUI *dialog)
+{
+  GSList *filters = NULL;
+  GSList *item = NULL;
+  const char *filter_uri = NULL;
+  GtkTreeIter iter;
+
+  filters = uri_tester_get_filters (dialog->priv->tester);
+  for (item = filters; item; item = g_slist_next (item))
+    {
+      filter_uri = (const char *) item->data;
+
+      gtk_list_store_append (dialog->priv->store, &iter);
+      gtk_list_store_set (dialog->priv->store, &iter, COL_FILTER_URI, filter_uri, -1);
+    }
+}
+
+static void
+adblock_ui_init (AdblockUI *dialog)
+{
+  LOG ("AdblockUI initialising");
+  dialog->priv = ADBLOCK_UI_GET_PRIVATE (dialog);
+}
+
+static void
+adblock_ui_constructed (GObject *object)
+{
+  AdblockUI *dialog;
+  AdblockUIPrivate *priv;
+  EphyDialog *edialog;
+
+  dialog = ADBLOCK_UI (object);
+  edialog = EPHY_DIALOG (object);
+
+  priv = dialog->priv;
+
+  ephy_dialog_construct (EPHY_DIALOG (edialog),
+                         SHARE_DIR "/ui/adblock.ui",
+                         "adblock-ui",
+                         GETTEXT_PACKAGE);
+
+  ephy_dialog_get_controls (edialog,
+                            "adblock-ui", &priv->dialog,
+                            "new_filter_entry", &priv->new_filter,
+                            "treeview", &priv->treeview,
+                            "add_button", &priv->add,
+                            "edit_button", &priv->edit,
+                            "remove_button", &priv->remove,
+                            NULL);
+
+  g_signal_connect (priv->dialog, "response",
+                    G_CALLBACK (adblock_ui_response_cb), dialog);
+
+  g_signal_connect (priv->add, "clicked",
+                    G_CALLBACK (adblock_ui_add_cb), dialog);
+  g_signal_connect (priv->edit, "clicked",
+                    G_CALLBACK (adblock_ui_edit_cb), dialog);
+  g_signal_connect (priv->remove, "clicked",
+                    G_CALLBACK (adblock_ui_remove_cb), dialog);
+  g_signal_connect (priv->new_filter, "activate",
+                    G_CALLBACK (adblock_ui_add_cb), dialog);
+
+  /* Build and fill. */
+  adblock_ui_build_treeview (dialog);
+  adblock_ui_populate_store (dialog);
+
+  /* Chain up. */
+  G_OBJECT_CLASS (adblock_ui_parent_class)->constructed (object);
+}
+
+static void
+adblock_ui_set_property (GObject *object,
+                         guint prop_id,
+                         const GValue *value,
+                         GParamSpec *pspec)
+{
+  AdblockUI *dialog = ADBLOCK_UI (object);
+
+  switch (prop_id)
+    {
+    case PROP_TESTER:
+      dialog->priv->tester = g_value_get_object (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+adblock_ui_class_init (AdblockUIClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = adblock_ui_constructed;
+  object_class->set_property = adblock_ui_set_property;
+
+  g_object_class_install_property
+    (object_class,
+     PROP_TESTER,
+     g_param_spec_object ("tester",
+                          "UriTester",
+                          "UriTester",
+                          TYPE_URI_TESTER,
+                          G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+  g_type_class_add_private (object_class, sizeof (AdblockUIPrivate));
+}
+
+static void adblock_ui_class_finalize (AdblockUIClass *klass)
+{
+}
+
+/* Public functions. */
+
+void adblock_ui_register (GTypeModule *module)
+{
+  adblock_ui_register_type (module);
+}
+
+AdblockUI *
+adblock_ui_new (UriTester *tester)
+{
+  return g_object_new (TYPE_ADBLOCK_UI,
+                       "tester", tester,
+                       NULL);
+}
diff --git a/extensions/adblock/adblock-ui.h b/extensions/adblock/adblock-ui.h
new file mode 100644
index 0000000..59a05e8
--- /dev/null
+++ b/extensions/adblock/adblock-ui.h
@@ -0,0 +1,62 @@
+/*
+ *  Copyright  2011 Igalia S.L.
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef ADBLOCK_UI_H
+#define ADBLOCK_UI_H
+
+#include "uri-tester.h"
+
+#include <epiphany/epiphany.h>
+#include <glib-object.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define TYPE_ADBLOCK_UI         (adblock_ui_get_type ())
+#define ADBLOCK_UI(o)           (G_TYPE_CHECK_INSTANCE_CAST((o), TYPE_ADBLOCK_UI, AdblockUI))
+#define ADBLOCK_UI_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TYPE_ADBLOCK_UI, AdblockUIClass))
+#define IS_ADBLOCK_UI(o)        (G_TYPE_CHECK_INSTANCE_TYPE((o), TYPE_ADBLOCK_UI))
+#define IS_ADBLOCK_UI_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE((k), TYPE_ADBLOCK_UI))
+#define ADBLOCK_UI_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), TYPE_ADBLOCK_UI, AdblockUIClass))
+
+typedef struct _AdblockUI        AdblockUI;
+typedef struct _AdblockUIClass   AdblockUIClass;
+typedef struct _AdblockUIPrivate AdblockUIPrivate;
+
+struct _AdblockUI
+{
+  EphyDialog parent;
+
+  /*< private >*/
+  AdblockUIPrivate *priv;
+};
+
+struct _AdblockUIClass
+{
+  EphyDialogClass parent_class;
+};
+
+GType      adblock_ui_get_type (void);
+
+void       adblock_ui_register (GTypeModule *module);
+
+AdblockUI *adblock_ui_new      (UriTester *tester);
+
+G_END_DECLS
+
+#endif
diff --git a/extensions/adblock/adblock.ephy-extension.in.in b/extensions/adblock/adblock.ephy-extension.in.in
new file mode 100644
index 0000000..5b50403
--- /dev/null
+++ b/extensions/adblock/adblock.ephy-extension.in.in
@@ -0,0 +1,10 @@
+[Epiphany Extension]
+_Name=Ad Blocker v2
+_Description=Block the pest!
+Authors=Mario Sanchez Prada <msanchez igalia com>
+Version=2
+URL=http://www.gnome.org/projects/epiphany/extensions.html
+
+[Loader]
+Type=shlib
+Library=%EXTENSION_DIR%/%LIBRARY%
diff --git a/extensions/adblock/adblock.ui b/extensions/adblock/adblock.ui
new file mode 100644
index 0000000..8831069
--- /dev/null
+++ b/extensions/adblock/adblock.ui
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <!-- interface-requires gtk+ 2.6 -->
+  <object class="GtkDialog" id="adblock-ui">
+    <property name="can_focus">False</property>
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Adblock Editor</property>
+    <property name="window_position">center-on-parent</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="type_hint">dialog</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="skip_pager_hint">True</property>
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">5</property>
+        <child>
+          <object class="GtkLabel" id="description_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="label" translatable="yes">Type the address of a preconfigured filter list in the text entry to be added to the list. Find more lists at easylist.adblockplus.org</property>
+            <property name="use_markup">True</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="padding">6</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox" id="dialog-action_area1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="close">
+                <property name="label">gtk-close</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_action_appearance">False</property>
+                <property name="use_stock">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="pack_type">end</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox" id="hbox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <child>
+              <object class="GtkBox" id="left_vbox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">6</property>
+                <child>
+                  <object class="GtkEntry" id="new_filter_entry">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="invisible_char">â</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkScrolledWindow" id="treeview_scroller">
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="shadow_type">in</property>
+                    <child>
+                      <object class="GtkTreeView" id="treeview">
+                        <property name="visible">True</property>
+                        <property name="can_focus">True</property>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection" id="treeview-selection1"/>
+                        </child>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="padding">4</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox" id="right_vbox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">6</property>
+                <child>
+                  <object class="GtkLabel" id="filler_label">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="add_button">
+                    <property name="label">gtk-add</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="use_stock">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="edit_button">
+                    <property name="label">gtk-edit</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="use_stock">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="remove_button">
+                    <property name="label">gtk-remove</property>
+                    <property name="visible">True</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="use_stock">True</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">False</property>
+                    <property name="position">3</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">False</property>
+                <property name="padding">4</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="padding">12</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-7">close</action-widget>
+    </action-widgets>
+  </object>
+</interface>
diff --git a/extensions/adblock/ephy-adblock-extension.c b/extensions/adblock/ephy-adblock-extension.c
new file mode 100644
index 0000000..ba9d7bd
--- /dev/null
+++ b/extensions/adblock/ephy-adblock-extension.c
@@ -0,0 +1,317 @@
+/*
+ *  Copyright  2011 Igalia S.L.
+ *
+ *  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.
+ *
+ *  Some parts of this file based on the previous 'adblock' extension,
+ *  licensed with the GNU General Public License 2 and later versions,
+ *  Copyright (C) 2003 Marco Pesenti Gritti, Christian Persch.
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "ephy-adblock-extension.h"
+
+#include "adblock-ui.h"
+#include "ephy-debug.h"
+#include "ephy-file-helpers.h"
+#include "uri-tester.h"
+
+#include <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+
+#define EPHY_ADBLOCK_EXTENSION_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), EPHY_TYPE_ADBLOCK_EXTENSION, EphyAdblockExtensionPrivate))
+
+#define WINDOW_DATA_KEY     "EphyAdblockExtensionWindowData"
+#define STATUSBAR_EVBOX_KEY "EphyAdblockExtensionStatusbarEvbox"
+#define EXTENSION_KEY       "EphyAdblockExtension"
+#define AD_BLOCK_ICON_NAME  "ad-blocked"
+
+typedef struct
+{
+  EphyAdblockExtension *extension;
+  EphyWindow           *window;
+
+  GtkActionGroup       *action_group;
+  guint                 ui_id;
+} WindowData;
+
+struct EphyAdblockExtensionPrivate
+{
+  UriTester *tester;
+  AdblockUI *ui;
+};
+
+static void ephy_adblock_extension_iface_init (EphyExtensionIface *iface);
+static void ephy_adblock_adblock_iface_init (EphyAdBlockIface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (EphyAdblockExtension,
+                                ephy_adblock_extension,
+                                G_TYPE_OBJECT,
+                                0,
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (EPHY_TYPE_ADBLOCK,
+                                                               ephy_adblock_adblock_iface_init)
+                                G_IMPLEMENT_INTERFACE_DYNAMIC (EPHY_TYPE_EXTENSION,
+                                                               ephy_adblock_extension_iface_init));
+
+/* Private functions. */
+
+static void
+ephy_adblock_extension_init (EphyAdblockExtension *extension)
+{
+  EphyAdBlockManager *manager = NULL;
+
+  LOG ("EphyAdblockExtension initialising");
+
+  extension->priv = EPHY_ADBLOCK_EXTENSION_GET_PRIVATE (extension);
+  extension->priv->tester = uri_tester_new ();
+
+  /* Register our extension as a blocker. */
+  manager = EPHY_ADBLOCK_MANAGER (ephy_embed_shell_get_adblock_manager (embed_shell));
+  ephy_adblock_manager_set_blocker (manager, EPHY_ADBLOCK (extension));
+}
+
+static void
+ephy_adblock_extension_dispose (GObject *object)
+{
+  EphyAdblockExtension *extension = NULL;
+
+  LOG ("EphyAdblockExtension disposing");
+
+  extension = EPHY_ADBLOCK_EXTENSION (object);
+  g_clear_object (&extension->priv->ui);
+  g_clear_object (&extension->priv->tester);
+
+  G_OBJECT_CLASS (ephy_adblock_extension_parent_class)->dispose (object);
+}
+
+static void
+ephy_adblock_extension_finalize (GObject *object)
+{
+  EphyAdBlockManager *manager = NULL;
+
+  LOG ("EphyAdblockExtension finalising");
+
+  /* Unregister our extension as a blocker. */
+  manager = EPHY_ADBLOCK_MANAGER (ephy_embed_shell_get_adblock_manager (embed_shell));
+  ephy_adblock_manager_set_blocker (manager, NULL);
+
+  G_OBJECT_CLASS (ephy_adblock_extension_parent_class)->finalize (object);
+}
+
+static void
+ephy_adblock_extension_class_init (EphyAdblockExtensionClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->dispose = ephy_adblock_extension_dispose;
+  object_class->finalize = ephy_adblock_extension_finalize;
+
+  g_type_class_add_private (object_class, sizeof (EphyAdblockExtensionPrivate));
+}
+
+static void
+ephy_adblock_extension_class_finalize (EphyAdblockExtensionClass *klass)
+{
+}
+
+static gboolean
+ephy_adblock_impl_should_load (EphyAdBlock *blocker,
+                               EphyEmbed *embed,
+                               const char *url,
+                               AdUriCheckType type)
+{
+  EphyAdblockExtension *self = NULL;
+  EphyWebView* web_view = NULL;
+  const char *address = NULL;
+
+  LOG ("ephy_adblock_impl_should_load checking %s", url);
+
+  self = EPHY_ADBLOCK_EXTENSION (blocker);
+  g_return_val_if_fail (self != NULL, TRUE);
+
+  web_view = ephy_embed_get_web_view (embed);
+  address = ephy_web_view_get_address (web_view);
+
+  return !uri_tester_test_uri (self->priv->tester, url, address, type);
+}
+
+static void
+ephy_adblock_impl_edit_rule (EphyAdBlock *blocker,
+                             const char *url,
+                             gboolean allowed)
+{
+  EphyAdblockExtension *self = NULL;
+  EphyAdblockExtensionPrivate *priv = NULL;
+
+  LOG ("ephy_adblock_impl_edit_rule %s with state %d", url, allowed);
+
+  self = EPHY_ADBLOCK_EXTENSION (blocker);
+  priv = self->priv;
+
+  if (priv->ui == NULL)
+    {
+      AdblockUI **ui;
+
+      /*
+       * TODO: url and allowed should be passed to the UI,
+       * so the user can actually do something with it.
+       */
+      priv->ui = adblock_ui_new (priv->tester);
+      ui = &priv->ui;
+
+      g_object_add_weak_pointer ((gpointer)priv->ui,
+                                 (gpointer *) ui);
+
+      ephy_dialog_set_parent (EPHY_DIALOG (priv->ui), NULL);
+    }
+
+  ephy_dialog_show (EPHY_DIALOG (priv->ui));
+}
+
+static void
+ephy_adblock_adblock_iface_init (EphyAdBlockIface *iface)
+{
+  iface->should_load = ephy_adblock_impl_should_load;
+  iface->edit_rule = ephy_adblock_impl_edit_rule;
+}
+
+static void
+ephy_adblock_extension_edit_cb (GtkAction *action, EphyWindow *window)
+{
+  WindowData *data = NULL;
+  EphyAdblockExtensionPrivate *priv = NULL;
+
+  data = g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY);
+  g_return_if_fail (data != NULL);
+
+  priv = data->extension->priv;
+
+  if (priv->ui == NULL)
+    {
+      AdblockUI **ui;
+
+      priv->ui = adblock_ui_new (priv->tester);
+      ui = &priv->ui;
+
+      g_object_add_weak_pointer ((gpointer)priv->ui,
+                                 (gpointer *) ui);
+    }
+
+  ephy_dialog_set_parent (EPHY_DIALOG (priv->ui), GTK_WIDGET (window));
+  ephy_dialog_show (EPHY_DIALOG (priv->ui));
+}
+
+static const GtkActionEntry edit_entries[] = {
+  { "EphyAdblockExtensionEdit", NULL,
+    N_("Ad Blocker"), NULL,
+    N_("Configure Ad Blocker filters"),
+    G_CALLBACK (ephy_adblock_extension_edit_cb) }
+};
+
+static void
+impl_attach_window (EphyExtension *ext,
+                    EphyWindow *window)
+{
+  WindowData *data = NULL;
+  GtkUIManager *manager = NULL;
+
+  /* Add adblock editor's menu entry. */
+  data = g_new (WindowData, 1);
+  g_object_set_data_full (G_OBJECT (window),
+                          WINDOW_DATA_KEY,
+                          data,
+                          g_free);
+
+  data->extension = EPHY_ADBLOCK_EXTENSION (ext);
+  data->window = window;
+
+  data->action_group = gtk_action_group_new ("EphyAdblockExtension");
+  gtk_action_group_set_translation_domain (data->action_group,
+                                           GETTEXT_PACKAGE);
+  gtk_action_group_add_actions (data->action_group, edit_entries,
+                                G_N_ELEMENTS(edit_entries), window);
+
+  manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window));
+
+  gtk_ui_manager_insert_action_group (manager, data->action_group, -1);
+
+  /* UI manager references the new action group. */
+  g_object_unref (data->action_group);
+
+  data->ui_id = gtk_ui_manager_new_merge_id (manager);
+
+  gtk_ui_manager_add_ui (manager,
+                         data->ui_id,
+                         "/menubar/ToolsMenu",
+                         "EphyAdblockExtensionEdit",
+                         "EphyAdblockExtensionEdit",
+                         GTK_UI_MANAGER_MENUITEM,
+                         FALSE);
+
+  /* Remember the xtension attached to that window. */
+  g_object_set_data (G_OBJECT (window), EXTENSION_KEY, ext);
+}
+
+static void
+impl_detach_window (EphyExtension *ext,
+                    EphyWindow *window)
+{
+  WindowData *data = NULL;
+  GtkUIManager *manager = NULL;
+
+  /* Remove editor UI. */
+  data = g_object_get_data (G_OBJECT (window), WINDOW_DATA_KEY);
+  g_assert (data != NULL);
+
+  manager = GTK_UI_MANAGER (ephy_window_get_ui_manager (window));
+
+  gtk_ui_manager_remove_ui (manager, data->ui_id);
+  gtk_ui_manager_remove_action_group (manager, data->action_group);
+
+  g_object_set_data (G_OBJECT (window), WINDOW_DATA_KEY, NULL);
+}
+
+static void
+impl_attach_tab (EphyExtension *ext,
+                 EphyWindow *window,
+                 EphyEmbed *embed)
+{
+
+}
+
+static void
+impl_detach_tab (EphyExtension *ext,
+                 EphyWindow *window,
+                 EphyEmbed *embed)
+{
+
+}
+
+static void
+ephy_adblock_extension_iface_init (EphyExtensionIface *iface)
+{
+  iface->attach_window = impl_attach_window;
+  iface->detach_window = impl_detach_window;
+  iface->attach_tab = impl_attach_tab;
+  iface->detach_tab = impl_detach_tab;
+}
+
+/* Public functions. */
+
+void
+ephy_adblock_extension_register (GTypeModule *module)
+{
+  ephy_adblock_extension_register_type (module);
+}
diff --git a/extensions/adblock/ephy-adblock-extension.h b/extensions/adblock/ephy-adblock-extension.h
new file mode 100644
index 0000000..1ece747
--- /dev/null
+++ b/extensions/adblock/ephy-adblock-extension.h
@@ -0,0 +1,58 @@
+/*
+ *  Copyright  2011 Igalia S.L.
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef EPHY_ADBLOCK_EXTENSION_H
+#define EPHY_ADBLOCK_EXTENSION_H
+
+#include <epiphany/epiphany.h>
+#include <glib-object.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_ADBLOCK_EXTENSION         (ephy_adblock_extension_get_type ())
+#define EPHY_ADBLOCK_EXTENSION(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), EPHY_TYPE_ADBLOCK_EXTENSION, EphyAdblockExtension))
+#define EPHY_ADBLOCK_EXTENSION_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), EPHY_TYPE_ADBLOCK_EXTENSION, EphyAdblockExtensionClass))
+#define EPHY_IS_ADBLOCK_EXTENSION(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), EPHY_TYPE_ADBLOCK_EXTENSION))
+#define EPHY_IS_ADBLOCK_EXTENSION_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), EPHY_TYPE_ADBLOCK_EXTENSION))
+#define EPHY_ADBLOCK_EXTENSION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EPHY_TYPE_ADBLOCK_EXTENSION, EphyAdblockExtensionClass))
+
+typedef struct EphyAdblockExtension        EphyAdblockExtension;
+typedef struct EphyAdblockExtensionClass   EphyAdblockExtensionClass;
+typedef struct EphyAdblockExtensionPrivate EphyAdblockExtensionPrivate;
+
+struct EphyAdblockExtensionClass
+{
+  GObjectClass parent_class;
+};
+
+struct EphyAdblockExtension
+{
+  GObject parent_instance;
+
+  /*< private >*/
+  EphyAdblockExtensionPrivate *priv;
+};
+
+GType ephy_adblock_extension_get_type (void);
+
+void  ephy_adblock_extension_register (GTypeModule *module);
+
+G_END_DECLS
+
+#endif
diff --git a/extensions/adblock/extension.c b/extensions/adblock/extension.c
new file mode 100644
index 0000000..6afe665
--- /dev/null
+++ b/extensions/adblock/extension.c
@@ -0,0 +1,44 @@
+/*
+ *  Copyright  2011 Igalia S.L.
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "adblock-ui.h"
+#include "uri-tester.h"
+#include "ephy-adblock-extension.h"
+#include "ephy-debug.h"
+
+#include <glib/gi18n-lib.h>
+
+G_MODULE_EXPORT GType
+register_module (GTypeModule *module)
+{
+  LOG ("Registering EphyAdblockExtension");
+
+#ifdef ENABLE_NLS
+  /* Initialise the i18n stuff. */
+  bindtextdomain (GETTEXT_PACKAGE, EPHY_EXTENSIONS_LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+#endif /* ENABLE_NLS */
+
+  adblock_ui_register (module);
+  uri_tester_register (module);
+  ephy_adblock_extension_register (module);
+
+  return ephy_adblock_extension_get_type ();
+}
diff --git a/extensions/adblock/uri-tester.c b/extensions/adblock/uri-tester.c
new file mode 100644
index 0000000..84049ec
--- /dev/null
+++ b/extensions/adblock/uri-tester.c
@@ -0,0 +1,820 @@
+/*
+ *  Copyright  2011 Igalia S.L.
+ *
+ *  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.
+ *
+ *  Some parts of this file based on the Midori's 'adblock' extension,
+ *  licensed with the GNU Lesser General Public License 2.1, Copyright
+ *  (C) 2009-2010 Christian Dywan <christian twotoasts de> and 2009
+ *  Alexander Butenko <a butenka gmail com>. Check Midori's web site
+ *  at http://www.twotoasts.de
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include "uri-tester.h"
+
+#include "ephy-debug.h"
+#include "ephy-file-helpers.h"
+
+#include <gio/gio.h>
+#include <glib/gstdio.h>
+#include <string.h>
+#include <webkit/webkit.h>
+
+#define DEFAULT_FILTER_URL "http://adblockplus.mozdev.org/easylist/easylist.txt";
+#define FILTERS_LIST_FILENAME "filters.list"
+#define SIGNATURE_SIZE 8
+#define UPDATE_FREQUENCY 24 * 60 * 60 /* In seconds */
+
+#define URI_TESTER_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object), TYPE_URI_TESTER, UriTesterPrivate))
+
+struct _UriTesterPrivate
+{
+  GSList *filters;
+
+  GHashTable* pattern;
+  GHashTable* keys;
+  GHashTable* optslist;
+  GHashTable* urlcache;
+};
+
+enum
+{
+  PROP_0,
+  PROP_FILTERS,
+};
+
+G_DEFINE_DYNAMIC_TYPE (UriTester, uri_tester, G_TYPE_OBJECT);
+
+/* Private functions. */
+
+static void uri_tester_class_init (UriTesterClass *klass);
+static void uri_tester_init (UriTester *dialog);
+
+static char *
+uri_tester_fixup_regexp (char* src);
+
+static gboolean
+uri_tester_parse_file_at_uri (UriTester* tester, const char* fileuri);
+
+static char *
+uri_tester_ensure_data_dir ()
+{
+  char* folder = NULL;
+
+  /* Ensure adblock's dir is there. */
+  folder = g_build_filename (ephy_dot_dir (), "extensions", "data", "adblock", NULL);
+  g_mkdir_with_parents (folder, 0700);
+
+  return folder;
+}
+
+static char*
+uri_tester_get_fileuri_for_url (const char* url)
+{
+  char* filename = NULL;
+  char* folder = NULL;
+  char* path = NULL;
+  char* uri = NULL;
+
+  if (!strncmp (url, "file", 4))
+    return g_strndup (url + 7, strlen (url) - 7);
+
+  folder = uri_tester_ensure_data_dir ();
+  filename = g_compute_checksum_for_string (G_CHECKSUM_MD5, url, -1);
+
+  path = g_build_filename (folder, filename, NULL);
+  uri = g_filename_to_uri (path, NULL, NULL);
+
+  g_free (filename);
+  g_free (path);
+  g_free (folder);
+
+  return uri;
+}
+
+static void
+uri_tester_download_notify_status_cb (WebKitDownload *download,
+                                      GParamSpec *pspec,
+                                      UriTester *tester)
+{
+  const char *dest = NULL;
+
+  if (webkit_download_get_status (download) != WEBKIT_DOWNLOAD_STATUS_FINISHED)
+    return;
+
+  LOG ("Download from %s to %s completed",
+       webkit_download_get_source_uri (download),
+       webkit_download_get_destination_uri (download));
+
+  /* Parse the file from disk. */
+  dest = webkit_download_get_destination_uri (download);
+  uri_tester_parse_file_at_uri (tester, dest);
+}
+
+static void
+uri_tester_retrieve_filter (UriTester *tester, const char *url, const char *fileuri)
+{
+  WebKitNetworkRequest* request = NULL;
+  WebKitDownload* download = NULL;
+
+  g_return_if_fail (IS_URI_TESTER (tester));
+  g_return_if_fail (url != NULL);
+  g_return_if_fail (fileuri != NULL);
+
+  request = webkit_network_request_new (url);
+  download = webkit_download_new (request);
+  g_object_unref (request);
+
+  webkit_download_set_destination_uri (download, fileuri);
+
+  g_signal_connect (download, "notify::status",
+                    G_CALLBACK (uri_tester_download_notify_status_cb), tester);
+
+  webkit_download_start (download);
+}
+
+static gboolean
+uri_tester_filter_is_valid (const char *fileuri)
+{
+  GFile *file = NULL;
+  GFileInfo *file_info = NULL;
+  gboolean result;
+
+  /* Now check if the local file is too old. */
+  file = g_file_new_for_uri (fileuri);
+  file_info = g_file_query_info (file,
+                                 G_FILE_ATTRIBUTE_TIME_MODIFIED,
+                                 G_FILE_QUERY_INFO_NONE,
+                                 NULL,
+                                 NULL);
+  result = FALSE;
+  if (file_info)
+    {
+      GTimeVal current_time;
+      GTimeVal mod_time;
+
+      g_get_current_time (&current_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 + UPDATE_FREQUENCY;
+          result = current_time.tv_sec < expire_time;
+        }
+      g_object_unref (file_info);
+    }
+
+  g_object_unref (file);
+
+  return result;
+}
+
+static void
+uri_tester_load_patterns (UriTester *tester)
+{
+  GSList *filter = NULL;
+  char *url = NULL;
+  char *fileuri = NULL;
+
+  /* Load patterns from the list of filters. */
+  for (filter = tester->priv->filters; filter; filter = g_slist_next(filter))
+    {
+      url = (char*)filter->data;
+      fileuri = uri_tester_get_fileuri_for_url (url);
+
+      if (!uri_tester_filter_is_valid (fileuri))
+        uri_tester_retrieve_filter (tester, url, fileuri);
+      else
+        uri_tester_parse_file_at_uri (tester, fileuri);
+
+      g_free (fileuri);
+    }
+}
+
+static void
+uri_tester_load_filters (UriTester *tester)
+{
+  GSList *list = NULL;
+  char *data_dir = NULL;
+  char *filepath = NULL;
+
+  data_dir =  uri_tester_ensure_data_dir ();
+  filepath = g_build_filename (data_dir, FILTERS_LIST_FILENAME, NULL);
+
+  if (g_file_test (filepath, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
+    {
+      GFile* file = NULL;
+      char *contents = NULL;
+      gsize length = 0;
+      GError *error = NULL;
+
+      file = g_file_new_for_path (filepath);
+      if (g_file_load_contents (file, NULL, &contents, &length, NULL, &error))
+        {
+          char **urls_array = NULL;
+          char *url = NULL;
+          int i = 0;
+
+          urls_array = g_strsplit (contents, ";", -1);
+          for (i = 0; urls_array [i]; i++)
+            {
+              url = g_strstrip (g_strdup (urls_array[i]));
+              if (!g_str_equal (url, ""))
+                list = g_slist_prepend (list, url);
+            }
+          g_strfreev (urls_array);
+
+          g_free (contents);
+        }
+
+      if (error)
+        {
+          LOG ("Error loading filters from %s: %s", filepath, error->message);
+          g_error_free (error);
+        }
+
+      g_object_unref (file);
+    }
+  else
+    {
+      /* No file exists yet, so use the default filter and save it. */
+      list = g_slist_prepend (list, g_strdup (DEFAULT_FILTER_URL));
+    }
+
+  g_free (filepath);
+
+  uri_tester_set_filters (tester, g_slist_reverse(list));
+}
+
+static void
+uri_tester_save_filters (UriTester *tester)
+{
+  FILE* file = NULL;
+  char *data_dir = NULL;
+  char *filepath = NULL;
+
+  data_dir =  uri_tester_ensure_data_dir ();
+  filepath = g_build_filename (data_dir, FILTERS_LIST_FILENAME, NULL);
+
+  if ((file = g_fopen (filepath, "w")))
+    {
+      GSList *item = NULL;
+      char *filter = NULL;
+
+      for (item = tester->priv->filters; item; item = g_slist_next (item))
+        {
+          filter = g_strdup_printf ("%s;", (char*)item->data);
+          fputs (filter, file);
+          g_free (filter);
+        }
+      fclose (file);
+    }
+  g_free (filepath);
+}
+
+static inline gboolean
+uri_tester_check_filter_options (GRegex*       regex,
+                                 const char*  opts,
+                                 const char*  req_uri,
+                                 const char*  page_uri)
+{
+  if (g_regex_match_simple (",third-party", opts,
+                            G_REGEX_CASELESS, G_REGEX_MATCH_NOTEMPTY))
+    {
+      if (page_uri && g_regex_match_full (regex, page_uri, -1, 0, 0, NULL, NULL))
+        return TRUE;
+    }
+
+  return FALSE;
+}
+
+static inline gboolean
+uri_tester_is_matched_by_pattern (UriTester *tester,
+                                  const char*  req_uri,
+                                  const char*  page_uri)
+{
+  GHashTableIter iter;
+  gpointer patt, regex;
+  char* opts;
+
+  g_hash_table_iter_init (&iter, tester->priv->pattern);
+  while (g_hash_table_iter_next (&iter, &patt, &regex))
+    {
+      if (g_regex_match_full (regex, req_uri, -1, 0, 0, NULL, NULL))
+        {
+          opts = g_hash_table_lookup (tester->priv->optslist, patt);
+          if (opts && uri_tester_check_filter_options (regex, opts, req_uri, page_uri) == TRUE)
+            return FALSE;
+          else
+            {
+              LOG ("blocked by pattern regexp=%s -- %s", g_regex_get_pattern (regex), req_uri);
+              return TRUE;
+            }
+        }
+    }
+  return FALSE;
+}
+
+static inline gboolean
+uri_tester_is_matched_by_key (UriTester *tester,
+                              const char*  opts,
+                              const char*  req_uri,
+                              const char*  page_uri)
+{
+  UriTesterPrivate* priv = NULL;
+  char* uri;
+  int len;
+  int pos = 0;
+  GList* regex_bl = NULL;
+
+  priv = tester->priv;
+
+  uri = uri_tester_fixup_regexp ((char*)req_uri);
+  len = strlen (uri);
+  for (pos = len - SIGNATURE_SIZE; pos >= 0; pos--)
+    {
+      char* sig = g_strndup (uri + pos, SIGNATURE_SIZE);
+      GRegex* regex = g_hash_table_lookup (priv->keys, sig);
+      char* opts = NULL;
+
+      if (regex && !g_list_find (regex_bl, regex))
+        {
+          if (g_regex_match_full (regex, req_uri, -1, 0, 0, NULL, NULL))
+            {
+              opts = g_hash_table_lookup (tester->priv->optslist, sig);
+              g_free (sig);
+              if (opts && uri_tester_check_filter_options (regex, opts, req_uri, page_uri))
+                {
+                  g_free (uri);
+                  g_list_free (regex_bl);
+                  return FALSE;
+                }
+              else
+                {
+                  LOG ("blocked by regexp=%s -- %s", g_regex_get_pattern (regex), uri);
+                  g_free (uri);
+                  g_list_free (regex_bl);
+                  return TRUE;
+                }
+            }
+          regex_bl = g_list_prepend (regex_bl, regex);
+        }
+      g_free (sig);
+    }
+  g_free (uri);
+  g_list_free (regex_bl);
+  return FALSE;
+}
+
+static gboolean
+uri_tester_is_matched (UriTester *tester,
+                       const char*  opts,
+                       const char*  req_uri,
+                       const char*  page_uri)
+{
+  UriTesterPrivate* priv = NULL;
+  gboolean foundbykey;
+  gboolean foundbypattern;
+  char* value;
+
+  priv = tester->priv;
+
+  /* Check cached URLs first. */
+  if ((value = g_hash_table_lookup (priv->urlcache, req_uri)))
+    return (value[0] != '0') ? TRUE : FALSE;
+
+  /* Look for a match either by key or by pattern. */
+  foundbykey = uri_tester_is_matched_by_key (tester, opts, req_uri, page_uri);
+  foundbypattern = uri_tester_is_matched_by_pattern (tester, req_uri, page_uri);
+
+  if (foundbykey || foundbypattern)
+    {
+      g_hash_table_insert (priv->urlcache, g_strdup (req_uri), g_strdup("1"));
+      return TRUE;
+    }
+  g_hash_table_insert (priv->urlcache, g_strdup (req_uri), g_strdup("0"));
+  return FALSE;
+}
+
+static char *
+uri_tester_fixup_regexp (char* src)
+{
+  char* dst;
+  GString* str;
+  int len;
+
+  if (!src)
+    return NULL;
+
+  str = g_string_new ("");
+
+  /* Lets strip first .* */
+  if (src[0] == '*')
+    {
+      (void)*src++;
+    }
+
+  do
+    {
+      switch (*src)
+        {
+        case '*':
+          g_string_append (str, ".*");
+          break;
+        /* case '.': */
+        /*   g_string_append (str, "\\."); */
+        /*   break; */
+        case '?':
+          g_string_append (str, "\\?");
+          break;
+        case '|':
+          g_string_append (str, "");
+          break;
+          /* FIXME: We actually need to match :[0-9]+ or '/'. Sign
+           * means "here could be port number or nothing". So bla.com^
+           * will match bla.com/ or bla.com:8080/ but not bla.com.au/.
+           */
+        case '^':
+          g_string_append (str, "");
+          break;
+        case '+':
+          break;
+        default:
+          g_string_append_printf (str,"%c", *src);
+          break;
+        }
+      src++;
+    }
+  while (*src);
+
+  dst = g_strdup (str->str);
+  g_string_free (str, TRUE);
+
+  /* We dont need .* in the end of url. Thats stupid. */
+  len = strlen (dst);
+  if (dst && dst[len-1] == '*' && dst[len-2] == '.')
+    {
+      dst[len-2] = '\0';
+    }
+  return dst;
+}
+
+static void
+uri_tester_compile_regexp (UriTester* tester,
+                           char*      patt,
+                           char*      opts)
+{
+  GRegex* regex;
+  GError* error = NULL;
+  int pos = 0;
+  char *sig;
+
+  regex = g_regex_new (patt, G_REGEX_OPTIMIZE,
+                       G_REGEX_MATCH_NOTEMPTY, &error);
+  if (error)
+    {
+      g_warning ("%s: %s", G_STRFUNC, error->message);
+      g_error_free (error);
+      return;
+    }
+
+  if (!g_regex_match_simple ("^/.*[\\^\\$\\*].*/$", patt, G_REGEX_UNGREEDY, G_REGEX_MATCH_NOTEMPTY))
+    {
+      int len = strlen (patt);
+      int signature_count = 0;
+      for (pos = len - SIGNATURE_SIZE; pos >= 0; pos--) {
+        sig = g_strndup (patt + pos, SIGNATURE_SIZE);
+        if (!g_regex_match_simple ("[\\*]", sig, G_REGEX_UNGREEDY, G_REGEX_MATCH_NOTEMPTY) &&
+            !g_hash_table_lookup (tester->priv->keys, sig))
+          {
+            LOG ("sig: %s %s", sig, patt);
+            g_hash_table_insert (tester->priv->keys, g_strdup (sig), g_regex_ref (regex));
+            g_hash_table_insert (tester->priv->optslist, g_strdup (sig), g_strdup (opts));
+            signature_count++;
+          }
+        else
+          {
+            if (g_regex_match_simple ("^\\*", sig, G_REGEX_UNGREEDY, G_REGEX_MATCH_NOTEMPTY) &&
+                !g_hash_table_lookup (tester->priv->pattern, patt))
+              {
+                LOG ("patt2: %s %s", sig, patt);
+                g_hash_table_insert (tester->priv->pattern, g_strdup (patt), g_regex_ref (regex));
+                g_hash_table_insert (tester->priv->optslist, g_strdup (patt), g_strdup (opts));
+              }
+          }
+        g_free (sig);
+      }
+      if (signature_count > 1 && g_hash_table_lookup (tester->priv->pattern, opts))
+        g_hash_table_steal (tester->priv->pattern, patt);
+    }
+  else
+    {
+      LOG ("patt: %s%s", patt, "");
+      /* Pattern is a regexp chars. */
+      g_hash_table_insert (tester->priv->pattern, g_strdup (patt), g_regex_ref (regex));
+      g_hash_table_insert (tester->priv->optslist, g_strdup (patt), g_strdup (opts));
+    }
+
+  g_regex_unref (regex);
+}
+
+static char*
+uri_tester_add_url_pattern (UriTester* tester,
+                            char* format,
+                            char* type,
+                            char* line)
+{
+  char** data;
+  char* patt;
+  char* fixed_patt;
+  char* format_patt;
+  char* opts;
+
+  data = g_strsplit (line, "$", -1);
+  if (data && data[0] && data[1] && data[2])
+    {
+      patt = g_strdup_printf ("%s%s", data[0], data[1]);
+      opts = g_strdup_printf ("type=%s,regexp=%s,%s", type, patt, data[2]);
+    }
+  else if (data && data[0] && data[1])
+    {
+      patt = g_strdup (data[0]);
+      opts = g_strdup_printf ("type=%s,regexp=%s,%s", type, patt, data[1]);
+    }
+  else
+    {
+      patt = g_strdup (data[0]);
+      opts = g_strdup_printf ("type=%s,regexp=%s", type, patt);
+    }
+
+  fixed_patt = uri_tester_fixup_regexp (patt);
+  format_patt =  g_strdup_printf (format, fixed_patt);
+
+  LOG ("got: %s opts %s", format_patt, opts);
+  uri_tester_compile_regexp (tester, format_patt, opts);
+
+  g_strfreev (data);
+  g_free (patt);
+  g_free (fixed_patt);
+  return format_patt;
+}
+
+static char*
+uri_tester_parse_line (UriTester* tester, char* line)
+{
+  if (!line)
+    return NULL;
+  g_strchomp (line);
+
+  /* Ignore comments and new lines. */
+  if (line[0] == '!')
+    return NULL;
+
+  /* FIXME: No support for whitelisting. */
+  if (line[0] == '@' && line[1] == '@')
+    return NULL;
+
+  /* FIXME: No support for [include] and [exclude] tags. */
+  if (line[0] == '[')
+    return NULL;
+
+  /* Got CSS block hider. */
+  if (line[0] == '#' && line[1] == '#' )
+    {
+      return NULL;
+    }
+  /* Got CSS block hider. Workaround. */
+  if (line[0] == '#')
+    return NULL;
+
+  /* Got per domain CSS hider rule. */
+  if (strstr (line, "##"))
+    {
+      return NULL;
+    }
+
+  /* Got per domain CSS hider rule. Workaround. */
+  if (strchr (line, '#'))
+    {
+      return NULL;
+    }
+  /* Got URL blocker rule. */
+  if (line[0] == '|' && line[1] == '|' )
+    {
+      (void)*line++;
+      (void)*line++;
+      return uri_tester_add_url_pattern (tester, "%s", "fulluri", line);
+    }
+  if (line[0] == '|')
+    {
+      (void)*line++;
+      return uri_tester_add_url_pattern (tester, "^%s", "fulluri", line);
+    }
+  return uri_tester_add_url_pattern (tester, "%s", "uri", line);
+}
+
+static gboolean
+uri_tester_parse_file_at_uri (UriTester* tester, const char* fileuri)
+{
+  FILE* file;
+  char line[2000];
+  char *path = NULL;
+  gboolean result = FALSE;
+
+  path = g_filename_from_uri (fileuri, NULL, NULL);
+  if ((file = g_fopen (path, "r")))
+    {
+      while (fgets (line, 2000, file))
+        g_free (uri_tester_parse_line (tester, line));
+      fclose (file);
+
+      result = TRUE;
+    }
+  g_free (path);
+
+  return result;
+}
+
+static void
+uri_tester_init (UriTester *tester)
+{
+  UriTesterPrivate* priv = NULL;
+
+  LOG ("UriTester initializing %p", tester);
+
+  priv = URI_TESTER_GET_PRIVATE (tester);
+  tester->priv = priv;
+
+  priv->filters = NULL;
+  priv->pattern = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                         (GDestroyNotify)g_free,
+                                         (GDestroyNotify)g_regex_unref);
+  priv->keys = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                      (GDestroyNotify)g_free,
+                                      (GDestroyNotify)g_regex_unref);
+  priv->optslist = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                          NULL,
+                                          (GDestroyNotify)g_free);
+  priv->urlcache = g_hash_table_new_full (g_str_hash, g_str_equal,
+                                          (GDestroyNotify)g_free,
+                                          (GDestroyNotify)g_free);
+
+  uri_tester_load_filters (tester);
+  uri_tester_load_patterns (tester);
+}
+
+static void
+uri_tester_set_property (GObject *object,
+                         guint prop_id,
+                         const GValue *value,
+                         GParamSpec *pspec)
+{
+  UriTester *tester = URI_TESTER (object);
+
+  switch (prop_id)
+    {
+    case PROP_FILTERS:
+      uri_tester_set_filters (tester, (GSList*) g_value_get_pointer (value));
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+uri_tester_finalize (GObject *object)
+{
+  UriTesterPrivate *priv = URI_TESTER_GET_PRIVATE (URI_TESTER (object));
+
+  LOG ("UriTester finalizing %p", object);
+
+  g_slist_foreach (priv->filters, (GFunc) g_free, NULL);
+  g_slist_free (priv->filters);
+
+  g_hash_table_destroy (priv->pattern);
+  g_hash_table_destroy (priv->keys);
+  g_hash_table_destroy (priv->optslist);
+  g_hash_table_destroy (priv->urlcache);
+
+  G_OBJECT_CLASS (uri_tester_parent_class)->finalize (object);
+}
+
+static void
+uri_tester_class_init (UriTesterClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->set_property = uri_tester_set_property;
+  object_class->finalize = uri_tester_finalize;
+
+  g_object_class_install_property
+    (object_class,
+     PROP_FILTERS,
+     g_param_spec_pointer ("filters",
+                           "filters",
+                           "filters",
+                           G_PARAM_WRITABLE));
+
+  g_type_class_add_private (object_class, sizeof (UriTesterPrivate));
+}
+
+static void
+uri_tester_class_finalize (UriTesterClass *klass)
+{
+}
+
+/* Public functions. */
+
+void uri_tester_register (GTypeModule *module)
+{
+  uri_tester_register_type (module);
+}
+
+UriTester *
+uri_tester_new (void)
+{
+  return g_object_new (TYPE_URI_TESTER, NULL);
+}
+
+gboolean
+uri_tester_test_uri (UriTester *tester,
+                     const char *req_uri,
+                     const char *page_uri,
+                     AdUriCheckType type)
+{
+  /* Don't block top level documents. */
+  if (type == AD_URI_CHECK_TYPE_DOCUMENT)
+    return FALSE;
+
+  return uri_tester_is_matched (tester, NULL, req_uri, page_uri);
+}
+
+void
+uri_tester_set_filters (UriTester *tester, GSList *filters)
+{
+  UriTesterPrivate *priv = tester->priv;
+
+  if (priv->filters)
+    {
+      g_slist_foreach (priv->filters, (GFunc) g_free, NULL);
+      g_slist_free (priv->filters);
+    }
+
+  /* Update private variable and save to disk. */
+  priv->filters = filters;
+  uri_tester_save_filters (tester);
+}
+
+GSList *
+uri_tester_get_filters (UriTester *tester)
+{
+  return tester->priv->filters;
+}
+
+void
+uri_tester_reload (UriTester *tester)
+{
+  GDir *g_data_dir = NULL;
+  const char *data_dir = NULL;
+
+  /* Remove data files in the data dir first. */
+  data_dir = uri_tester_ensure_data_dir ();
+
+  g_data_dir = g_dir_open (data_dir, 0, NULL);
+  if (g_data_dir)
+    {
+      const char *filename = NULL;
+      char *filepath = NULL;
+
+      while ((filename = g_dir_read_name (g_data_dir)))
+        {
+          /* Omit the list of filters. */
+          if (!g_strcmp0 (filename, FILTERS_LIST_FILENAME))
+            continue;
+
+          filepath = g_build_filename (data_dir, filename, NULL);
+          g_unlink (filepath);
+
+          g_free (filepath);
+        }
+
+      g_dir_close (g_data_dir);
+    }
+
+  /* Load patterns from current filters. */
+  uri_tester_load_patterns (tester);
+}
diff --git a/extensions/adblock/uri-tester.h b/extensions/adblock/uri-tester.h
new file mode 100644
index 0000000..698e3a1
--- /dev/null
+++ b/extensions/adblock/uri-tester.h
@@ -0,0 +1,71 @@
+/*
+ *  Copyright  2011 Igalia S.L.
+ *
+ *  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, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef URI_TESTER_H
+#define URI_TESTER_H
+
+#include <epiphany/epiphany.h>
+#include <glib-object.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define TYPE_URI_TESTER         (uri_tester_get_type ())
+#define URI_TESTER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_URI_TESTER, UriTester))
+#define URI_TESTER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), TYPE_URI_TESTER, UriTesterClass))
+#define IS_URI_TESTER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_URI_TESTER))
+#define IS_URI_TESTER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_URI_TESTER))
+#define URI_TESTER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_URI_TESTER, UriTesterClass))
+
+typedef struct _UriTester        UriTester;
+typedef struct _UriTesterClass   UriTesterClass;
+typedef struct _UriTesterPrivate UriTesterPrivate;
+
+struct _UriTester
+{
+  GObject parent_instance;
+
+  /*< private >*/
+  UriTesterPrivate *priv;
+};
+
+struct _UriTesterClass
+{
+  GObjectClass parent_class;
+};
+
+GType      uri_tester_get_type    (void);
+
+void       uri_tester_register    (GTypeModule *module);
+
+UriTester *uri_tester_new         (void);
+
+gboolean   uri_tester_test_uri    (UriTester *tester,
+                                   const char *req_uri,
+                                   const char *page_uri,
+                                   AdUriCheckType type);
+
+void       uri_tester_set_filters (UriTester *tester, GSList *filters);
+
+GSList    *uri_tester_get_filters (UriTester *tester);
+
+void       uri_tester_reload      (UriTester *tester);
+
+G_END_DECLS
+
+#endif /* URI_TESTER_H */



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