WebKit Bugzilla
Attachment 362488 Details for
Bug 167941
: [WPE][GTK] Enable support for CONTENT_EXTENSIONS
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch v13
bug-167941-20190220113346.patch (text/plain), 105.41 KB, created by
Adrian Perez
on 2019-02-20 01:33:47 PST
(
hide
)
Description:
Patch v13
Filename:
MIME Type:
Creator:
Adrian Perez
Created:
2019-02-20 01:33:47 PST
Size:
105.41 KB
patch
obsolete
>Subversion Revision: 241789 >diff --git a/Source/WTF/ChangeLog b/Source/WTF/ChangeLog >index 6b7ff09377f64f9713efe06a0744b30387a4a79b..29e79f7d941c4c9d9b1538f31a9c4d2624817b8e 100644 >--- a/Source/WTF/ChangeLog >+++ b/Source/WTF/ChangeLog >@@ -1,3 +1,17 @@ >+2019-02-19 Adrian Perez de Castro <aperez@igalia.com> >+ >+ [WPE][GTK] Enable support for CONTENT_EXTENSIONS >+ https://bugs.webkit.org/show_bug.cgi?id=167941 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add specialization of the refGPtr() and derefGPtr() templates for GMappedFile. >+ >+ * wtf/glib/GRefPtr.cpp: >+ (WTF::refGPtr): Added. >+ (WTF::derefGPtr): Added. >+ * wtf/glib/GRefPtr.h: Declare template specializations. >+ > 2019-02-19 Commit Queue <commit-queue@webkit.org> > > Unreviewed, rolling out r241770. >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 05648c595cecd326d58fd43629ca20f5e29c7e5b..c94b86aa5ba75f6ea91fe2f205b8a41ab5da34c6 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,13 @@ >+2019-02-19 Adrian Perez de Castro <aperez@igalia.com> >+ >+ [WPE][GTK] Enable support for CONTENT_EXTENSIONS >+ https://bugs.webkit.org/show_bug.cgi?id=167941 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * platform/gtk/po/POTFILES.in: Added WebKitUserContentFilterStore.cpp >+ to the list of files with translatable strings. >+ > 2019-02-19 Simon Fraser <simon.fraser@apple.com> > > REGRESSION (r238090): Toggling visibility on the <html> element can result in a blank web view >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 91019bbd17aae0420b71784a6108119c31f7091c..dd3311c0f3c6236a932f286677e17d60ed93bbc1 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,79 @@ >+2019-02-19 Adrian Perez de Castro <aperez@igalia.com> >+ >+ [WPE][GTK] Enable support for CONTENT_EXTENSIONS >+ https://bugs.webkit.org/show_bug.cgi?id=167941 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Adds new API to manage a collection of content extensions on disk (including compilation >+ of new ones) using WebKitUserContentFilterStore; the associated WebKitUserContentFilter >+ type (which represents a compiled content extension); and the functions needed to enable >+ and disable them for a given WebKitUserContentManager. >+ >+ The WebKitUserContentFilterStore public API is expressed in abstract terms of "saving" >+ filters into the store (which involves compiling the JSON source rule set); and "loading" >+ them back as main operations. This way we do not disclose to users of the API any detail >+ about compilation, nor how contents are laid out on disk, and the documentation explicitly >+ tells about only using the provided functions to manipulate the on-disk contents. This >+ way we allow ourselves some leeway if the implementation needs changing in the future. >+ >+ * PlatformGTK.cmake: Added WebKitUserContentFilterStore.h to the list of public API headers. >+ * PlatformWPE.cmake: Ditto. >+ * SourcesGTK.txt: Added WebKitUserContentFilterStore.cpp >+ * SourcesWPE.txt: Ditto. >+ * UIProcess/API/glib/WebKitError.cpp: Add definition of webkit_user_content_filter_error_quark(). >+ * UIProcess/API/glib/WebKitUserContent.cpp: Added WebKitUserContentFilter. >+ (_WebKitUserContentFilter::_WebKitUserContentFilter): >+ (webkit_user_content_filter_ref): >+ (webkit_user_content_filter_unref): >+ (webkit_user_content_filter_get_identifier): >+ (webkitUserContentFilterCreate): >+ (webkitUserContentFilterGetContentRuleList): >+ * UIProcess/API/glib/WebKitUserContentFilterStore.cpp: Added. >+ (toGError): Utility function to convert content extension error codes to GError. >+ (webkit_user_content_filter_store_class_init): >+ (webkit_user_content_filter_store_new): >+ (webkit_user_content_filter_store_get_path): >+ (webkitUserContentFilterStoreSaveBytes): Common function used as final step for all the >+ functions which save (compile) JSON rule sets into the store, to avoid duplicating code. >+ (webkit_user_content_filter_store_save): >+ (webkit_user_content_filter_store_save_finish): >+ (webkit_user_content_filter_store_save_from_file): >+ (webkit_user_content_filter_store_save_from_file_finish): >+ (webkit_user_content_filter_store_remove): >+ (webkit_user_content_filter_store_remove_finish): >+ (webkit_user_content_filter_store_load): >+ (webkit_user_content_filter_store_lookup_finish): >+ (webkit_user_content_filter_store_fetch_identifiers): >+ (webkit_user_content_filter_store_fetch_identifiers_finish): >+ * UIProcess/API/glib/WebKitUserContentManager.cpp: Added definitions for the new API >+ functions to add and remove filters from an user content manager. >+ (webkit_user_content_manager_add_filter): >+ (webkit_user_content_manager_remove_filter): >+ (webkit_user_content_manager_remove_all_filters): >+ * UIProcess/API/glib/WebKitUserContentPrivate.h: Added declarations for >+ webkitUserContentFilterCreate() and webkitUserContentFilterGetContentRuleList(). >+ * UIProcess/API/gtk/WebKitAutocleanups.h: Added autocleanups for WebKitUserContentFilter >+ and WebKitUserContentFilterStore. >+ * UIProcess/API/gtk/WebKitError.h: Added declarations for WEBKIT_USER_CONTENT_FILTER_ERROR >+ plus the associated webkit_user_content_filter_error_quark() function and >+ WebKitUserContentFilterErrror enum. >+ * UIProcess/API/gtk/WebKitUserContent.h: Added declarations for WebKitUserContentFilter >+ and its associated functions. >+ * UIProcess/API/gtk/WebKitUserContentFilterStore.h: Added. >+ * UIProcess/API/gtk/WebKitUserContentManager.h: Added declarations for the functions to >+ add and remove filters from the user content manager. >+ * UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt: Added new API functions and types to >+ be included in the documentation. >+ * UIProcess/API/gtk/webkit2.h: Added inclusion of WebKitUserContentFilterStore.h >+ * UIProcess/API/wpe/WebKitError.h: Same as for the GTK port header. >+ * UIProcess/API/wpe/WebKitUserContent.h: Same as for the GTK port header. >+ * UIProcess/API/wpe/WebKitUserContentFilterStore.h: Added. >+ * UIProcess/API/wpe/WebKitUserContentManager.h: Same as for the GTK port header. >+ * UIProcess/API/wpe/docs/wpe-0.1-sections.txt: Added new API functions and types to be >+ included in the documentation. >+ * UIProcess/API/wpe/webkit.h: Added inclusion of WebKitUserContentFilterStore.h >+ > 2019-02-19 Antti Koivisto <antti@apple.com> > > Pass rootContentsLayer to Mac remote layer tree >diff --git a/Source/WTF/wtf/glib/GRefPtr.cpp b/Source/WTF/wtf/glib/GRefPtr.cpp >index 2dd06fc8a652c8f76708d757b2124e3166835928..c413ed42cc801f7f0839d7274a9898fc9567d644 100644 >--- a/Source/WTF/wtf/glib/GRefPtr.cpp >+++ b/Source/WTF/wtf/glib/GRefPtr.cpp >@@ -169,6 +169,19 @@ template <> void derefGPtr(GRegex* ptr) > g_regex_unref(ptr); > } > >+template <> GMappedFile* refGPtr(GMappedFile* ptr) >+{ >+ if (ptr) >+ g_mapped_file_ref(ptr); >+ return ptr; >+} >+ >+template <> void derefGPtr(GMappedFile* ptr) >+{ >+ if (ptr) >+ g_mapped_file_unref(ptr); >+} >+ > } // namespace WTF > > #endif // USE(GLIB) >diff --git a/Source/WTF/wtf/glib/GRefPtr.h b/Source/WTF/wtf/glib/GRefPtr.h >index aaa16de2d6adf21c3902e0ddf9609ae0fb7d1748..06133d82cb35dc58d67cce13b4dfb1a54e750a60 100644 >--- a/Source/WTF/wtf/glib/GRefPtr.h >+++ b/Source/WTF/wtf/glib/GRefPtr.h >@@ -239,6 +239,8 @@ template <> WTF_EXPORT_PRIVATE GClosure* refGPtr(GClosure*); > template <> WTF_EXPORT_PRIVATE void derefGPtr(GClosure*); > template <> WTF_EXPORT_PRIVATE GRegex* refGPtr(GRegex*); > template <> WTF_EXPORT_PRIVATE void derefGPtr(GRegex*); >+template <> WTF_EXPORT_PRIVATE GMappedFile* refGPtr(GMappedFile*); >+template <> WTF_EXPORT_PRIVATE void derefGPtr(GMappedFile*); > > template <typename T> inline T* refGPtr(T* ptr) > { >diff --git a/Source/WebCore/platform/gtk/po/POTFILES.in b/Source/WebCore/platform/gtk/po/POTFILES.in >index 3ec09dbae41637e1032b8fa47266ee2f71668220..51ab506ad41a08c1d037006262d7ffd9f8464dae 100644 >--- a/Source/WebCore/platform/gtk/po/POTFILES.in >+++ b/Source/WebCore/platform/gtk/po/POTFILES.in >@@ -19,6 +19,7 @@ LocalizedStringsGtk.cpp > ../../../WebKit/UIProcess/API/glib/WebKitNotification.cpp > ../../../WebKit/UIProcess/API/glib/WebKitResponsePolicyDecision.cpp > ../../../WebKit/UIProcess/API/glib/WebKitSettings.cpp >+../../../WebKit/UIProcess/API/glib/WebKitUserContentFilterStore.cpp > ../../../WebKit/UIProcess/API/glib/WebKitUserMediaPermissionRequest.cpp > ../../../WebKit/UIProcess/API/glib/WebKitWebContext.cpp > ../../../WebKit/UIProcess/API/glib/WebKitWebResource.cpp >diff --git a/Source/WebKit/PlatformGTK.cmake b/Source/WebKit/PlatformGTK.cmake >index 634b0003d951e14879de2309977c763a8c4bda85..16dc61a20aec192d2d8f7a335362bef87ac6c4a2 100644 >--- a/Source/WebKit/PlatformGTK.cmake >+++ b/Source/WebKit/PlatformGTK.cmake >@@ -109,6 +109,7 @@ set(WebKit2GTK_INSTALLED_HEADERS > ${WEBKIT_DIR}/UIProcess/API/gtk/WebKitURISchemeRequest.h > ${WEBKIT_DIR}/UIProcess/API/gtk/WebKitURIUtilities.h > ${WEBKIT_DIR}/UIProcess/API/gtk/WebKitUserContent.h >+ ${WEBKIT_DIR}/UIProcess/API/gtk/WebKitUserContentFilterStore.h > ${WEBKIT_DIR}/UIProcess/API/gtk/WebKitUserContentManager.h > ${WEBKIT_DIR}/UIProcess/API/gtk/WebKitUserMediaPermissionRequest.h > ${WEBKIT_DIR}/UIProcess/API/gtk/WebKitWebContext.h >diff --git a/Source/WebKit/PlatformWPE.cmake b/Source/WebKit/PlatformWPE.cmake >index 0fbe5e2542543c90f9c720614f5985e1b0e7f30a..7084904d1b3dd599b31f898b199fe05f5d3b38ce 100644 >--- a/Source/WebKit/PlatformWPE.cmake >+++ b/Source/WebKit/PlatformWPE.cmake >@@ -133,6 +133,7 @@ set(WPE_API_INSTALLED_HEADERS > ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitURISchemeRequest.h > ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitURIUtilities.h > ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitUserContent.h >+ ${WEBKIT_DIR}/UIProcess/API/gtk/WebKitUserContentFilterStore.h > ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitUserContentManager.h > ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitUserMediaPermissionRequest.h > ${WEBKIT_DIR}/UIProcess/API/wpe/WebKitWebContext.h >diff --git a/Source/WebKit/SourcesGTK.txt b/Source/WebKit/SourcesGTK.txt >index 90d890eea7bfe7bf84d4fdf6b26dfefb30fd69fe..ea1bf97f89312727ce922c1a0ce4c20f23346ccb 100644 >--- a/Source/WebKit/SourcesGTK.txt >+++ b/Source/WebKit/SourcesGTK.txt >@@ -175,6 +175,7 @@ UIProcess/API/glib/WebKitUIClient.cpp @no-unify > UIProcess/API/glib/WebKitURISchemeRequest.cpp @no-unify > UIProcess/API/glib/WebKitURIUtilities.cpp @no-unify > UIProcess/API/glib/WebKitUserContent.cpp @no-unify >+UIProcess/API/glib/WebKitUserContentFilterStore.cpp @no-unify > UIProcess/API/glib/WebKitUserContentManager.cpp @no-unify > UIProcess/API/glib/WebKitUserMediaPermissionRequest.cpp @no-unify > UIProcess/API/glib/WebKitVersion.cpp @no-unify >diff --git a/Source/WebKit/SourcesWPE.txt b/Source/WebKit/SourcesWPE.txt >index 765c69d519df2998b2851beb607f3c5931885930..d39d553b27bfa4358e66d445f185d74cb7febeb4 100644 >--- a/Source/WebKit/SourcesWPE.txt >+++ b/Source/WebKit/SourcesWPE.txt >@@ -157,6 +157,7 @@ UIProcess/API/glib/WebKitUIClient.cpp @no-unify > UIProcess/API/glib/WebKitURISchemeRequest.cpp @no-unify > UIProcess/API/glib/WebKitURIUtilities.cpp @no-unify > UIProcess/API/glib/WebKitUserContent.cpp @no-unify >+UIProcess/API/glib/WebKitUserContentFilterStore.cpp @no-unify > UIProcess/API/glib/WebKitUserContentManager.cpp @no-unify > UIProcess/API/glib/WebKitUserMediaPermissionRequest.cpp @no-unify > UIProcess/API/glib/WebKitVersion.cpp @no-unify >diff --git a/Source/WebKit/UIProcess/API/glib/WebKitError.cpp b/Source/WebKit/UIProcess/API/glib/WebKitError.cpp >index ae9f74fc06018ef28b94f276805d5603d5ac7765..3e581c69c411fd9fc6ba1567cb5d591259de419d 100644 >--- a/Source/WebKit/UIProcess/API/glib/WebKitError.cpp >+++ b/Source/WebKit/UIProcess/API/glib/WebKitError.cpp >@@ -71,3 +71,5 @@ GQuark webkit_snapshot_error_quark() > { > return g_quark_from_static_string("WebKitSnapshotError"); > } >+ >+G_DEFINE_QUARK(WebKitUserContentFilterError, webkit_user_content_filter_error) >diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUserContent.cpp b/Source/WebKit/UIProcess/API/glib/WebKitUserContent.cpp >index acce07fa8c916faff0666213205af4023049d68c..80ef5427e669bf7d56702c53559c42c4a1841b11 100644 >--- a/Source/WebKit/UIProcess/API/glib/WebKitUserContent.cpp >+++ b/Source/WebKit/UIProcess/API/glib/WebKitUserContent.cpp >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2014 Igalia S.L. >+ * Copyright (C) 2014, 2018-2019 Igalia S.L. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Library General Public >@@ -317,3 +317,85 @@ API::UserScript& webkitUserScriptGetUserScript(WebKitUserScript* userScript) > { > return *userScript->userScript; > } >+ >+ >+struct _WebKitUserContentFilter { >+ _WebKitUserContentFilter(RefPtr<API::ContentRuleList>&& contentRuleList) >+ : identifier(contentRuleList->name().utf8()) >+ , contentRuleList(WTFMove(contentRuleList)) >+ , referenceCount(1) >+ { >+ } >+ >+ CString identifier; >+ RefPtr<API::ContentRuleList> contentRuleList; >+ int referenceCount; >+}; >+ >+G_DEFINE_BOXED_TYPE(WebKitUserContentFilter, webkit_user_content_filter, webkit_user_content_filter_ref, webkit_user_content_filter_unref) >+ >+/** >+ * webkit_user_content_filter_ref: >+ * @user_content_filter: A #WebKitUserContentFilter >+ * >+ * Atomically increments the reference count of @user_content_filter by one. >+ * This function is MT-safe and may be called from any thread. >+ * >+ * Since: 2.24 >+ */ >+WebKitUserContentFilter* webkit_user_content_filter_ref(WebKitUserContentFilter* userContentFilter) >+{ >+ g_return_val_if_fail(userContentFilter, nullptr); >+ g_atomic_int_inc(&userContentFilter->referenceCount); >+ return userContentFilter; >+} >+ >+/** >+ * webkit_user_content_filter_unref: >+ * @user_content_filter: A #WebKitUserContentFilter >+ * >+ * Atomically decrements the reference count of @user_content_filter by one. >+ * If the reference count drops to 0, all the memory allocated by the >+ * #WebKitUserContentFilter is released. This function is MT-safe and may >+ * be called from any thread. >+ * >+ * Since: 2.24 >+ */ >+void webkit_user_content_filter_unref(WebKitUserContentFilter* userContentFilter) >+{ >+ g_return_if_fail(userContentFilter); >+ if (g_atomic_int_dec_and_test(&userContentFilter->referenceCount)) { >+ userContentFilter->~WebKitUserContentFilter(); >+ fastFree(userContentFilter); >+ } >+} >+ >+/** >+ * webkit_user_content_filter_get_identifier: >+ * @user_content_filter: A #WebKitUserContentFilter >+ * >+ * Obtain the identifier previously used to save the @user_content_filter in the >+ * #WebKitUserContentFilterStore. >+ * >+ * Returns: (transfer none): the identifier for the filter >+ * >+ * Since: 2.24 >+ */ >+const char* webkit_user_content_filter_get_identifier(WebKitUserContentFilter* userContentFilter) >+{ >+ g_return_val_if_fail(userContentFilter, nullptr); >+ return userContentFilter->identifier.data(); >+} >+ >+WebKitUserContentFilter* webkitUserContentFilterCreate(RefPtr<API::ContentRuleList>&& contentRuleList) >+{ >+ WebKitUserContentFilter* userContentFilter = static_cast<WebKitUserContentFilter*>(fastMalloc(sizeof(WebKitUserContentFilter))); >+ new (userContentFilter) WebKitUserContentFilter(WTFMove(contentRuleList)); >+ return userContentFilter; >+} >+ >+API::ContentRuleList& webkitUserContentFilterGetContentRuleList(WebKitUserContentFilter* userContentFilter) >+{ >+ ASSERT(userContentFilter); >+ return *userContentFilter->contentRuleList; >+} >diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUserContentFilterStore.cpp b/Source/WebKit/UIProcess/API/glib/WebKitUserContentFilterStore.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..53e0269e07a4b190339baeeaebe3881e7a32bc7f >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/glib/WebKitUserContentFilterStore.cpp >@@ -0,0 +1,494 @@ >+/* >+ * Copyright (C) 2018-2019 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#include "config.h" >+#include "WebKitUserContentFilterStore.h" >+ >+#include "APIContentRuleList.h" >+#include "APIContentRuleListStore.h" >+#include "ContentExtensionError.h" >+#include "WebKitError.h" >+#include "WebKitUserContent.h" >+#include "WebKitUserContentPrivate.h" >+#include <glib/gi18n-lib.h> >+#include <wtf/CompletionHandler.h> >+#include <wtf/FileSystem.h> >+#include <wtf/RefPtr.h> >+#include <wtf/glib/GRefPtr.h> >+#include <wtf/glib/GUniquePtr.h> >+#include <wtf/glib/WTFGType.h> >+ >+/** >+ * SECTION: WebKitUserContentFilterStore >+ * @Short_description: Handles storage of user content filters on disk. >+ * @Title: WebKitUserContentFilterStore >+ * >+ * The WebKitUserContentFilterStore provides the means to import and save >+ * [JSON rule sets](https://webkit.org/blog/3476/content-blockers-first-look/), >+ * which can be loaded later in an efficient manner. Once filters are stored, >+ * the #WebKitUserContentFilter objects which represent them can be added to >+ * a #WebKitUserContentManager with webkit_user_content_manager_add_filter(). >+ * >+ * JSON rule sets are imported using webkit_user_content_filter_store_save() and stored >+ * on disk in an implementation defined format. The contents of a filter store must be >+ * managed using the #WebKitUserContentFilterStore: a list of all the stored filters >+ * can be obtained with webkit_user_content_filter_store_fetch_identifiers(), >+ * webkit_user_content_filter_store_load() can be used to retrieve a previously saved >+ * filter, and removed from the store with webkit_user_content_filter_store_remove(). >+ * >+ * Since: 2.24 >+ */ >+ >+enum { >+ PROP_0, >+ >+ PROP_PATH, >+}; >+ >+static inline GError* toGError(WebKitUserContentFilterError code, const std::error_code error) >+{ >+ ASSERT(error); >+ ASSERT(error.category() == WebCore::ContentExtensions::contentExtensionErrorCategory()); >+ return g_error_new_literal(WEBKIT_USER_CONTENT_FILTER_ERROR, code, error.message().c_str()); >+} >+ >+struct _WebKitUserContentFilterStorePrivate { >+ GUniquePtr<char> storagePath; >+ RefPtr<API::ContentRuleListStore> store; >+}; >+ >+WEBKIT_DEFINE_TYPE(WebKitUserContentFilterStore, webkit_user_content_filter_store, G_TYPE_OBJECT) >+ >+static void webkitUserContentFilterStoreGetProperty(GObject* object, guint propID, GValue* value, GParamSpec* paramSpec) >+{ >+ WebKitUserContentFilterStore* store = WEBKIT_USER_CONTENT_FILTER_STORE(object); >+ >+ switch (propID) { >+ case PROP_PATH: >+ g_value_set_string(value, webkit_user_content_filter_store_get_path(store)); >+ break; >+ default: >+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec); >+ } >+} >+ >+static void webkitUserContentFilterStoreSetProperty(GObject* object, guint propID, const GValue* value, GParamSpec* paramSpec) >+{ >+ WebKitUserContentFilterStore* store = WEBKIT_USER_CONTENT_FILTER_STORE(object); >+ >+ switch (propID) { >+ case PROP_PATH: >+ store->priv->storagePath.reset(g_value_dup_string(value)); >+ break; >+ default: >+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propID, paramSpec); >+ } >+} >+ >+static void webkitUserContentFilterStoreConstructed(GObject* object) >+{ >+ G_OBJECT_CLASS(webkit_user_content_filter_store_parent_class)->constructed(object); >+ >+ WebKitUserContentFilterStore* store = WEBKIT_USER_CONTENT_FILTER_STORE(object); >+ store->priv->store = adoptRef(new API::ContentRuleListStore(FileSystem::stringFromFileSystemRepresentation(store->priv->storagePath.get()), false)); >+} >+ >+static void webkit_user_content_filter_store_class_init(WebKitUserContentFilterStoreClass* storeClass) >+{ >+ GObjectClass* gObjectClass = G_OBJECT_CLASS(storeClass); >+ >+ gObjectClass->get_property = webkitUserContentFilterStoreGetProperty; >+ gObjectClass->set_property = webkitUserContentFilterStoreSetProperty; >+ gObjectClass->constructed = webkitUserContentFilterStoreConstructed; >+ >+ /** >+ * WebKitUserContentFilterStore:path: >+ * >+ * The directory used for filter storage. This path is used as the base >+ * directory where user content filters are stored on disk. >+ * >+ * Since: 2.24 >+ */ >+ g_object_class_install_property( >+ gObjectClass, >+ PROP_PATH, >+ g_param_spec_string( >+ "path", >+ _("Storage directory path"), >+ _("The directory where user content filters are stored"), >+ nullptr, >+ static_cast<GParamFlags>(WEBKIT_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY))); >+} >+ >+/** >+ * webkit_user_content_filter_store_new: >+ * @storage_path: path where data for filters will be stored on disk >+ * >+ * Create a new #WebKitUserContentFilterStore to manipulate filters stored at @storage_path. >+ * The path must point to a local filesystem, and will be created if needed. >+ * >+ * Returns: (transfer full): a newly created #WebKitUserContentFilterStore >+ * >+ * Since: 2.24 >+ */ >+WebKitUserContentFilterStore* webkit_user_content_filter_store_new(const gchar* storagePath) >+{ >+ g_return_val_if_fail(storagePath, nullptr); >+ return WEBKIT_USER_CONTENT_FILTER_STORE(g_object_new(WEBKIT_TYPE_USER_CONTENT_FILTER_STORE, "path", storagePath, nullptr)); >+} >+ >+/** >+ * webkit_user_content_filter_store_get_path: >+ * @store: a #WebKitUserContentFilterStore >+ * >+ * Returns: (transfer none): The storage path for user content filters. >+ * >+ * Since: 2.24 >+ */ >+const char* webkit_user_content_filter_store_get_path(WebKitUserContentFilterStore* store) >+{ >+ g_return_val_if_fail(WEBKIT_IS_USER_CONTENT_FILTER_STORE(store), nullptr); >+ return store->priv->storagePath.get(); >+} >+ >+static void webkitUserContentFilterStoreSaveBytes(GRefPtr<GTask>&& task, String&& identifier, GRefPtr<GBytes>&& source) >+{ >+ size_t sourceSize; >+ const char* sourceData = static_cast<const char*>(g_bytes_get_data(source.get(), &sourceSize)); >+ if (!sourceSize) { >+ g_task_return_error(task.get(), g_error_new_literal(WEBKIT_USER_CONTENT_FILTER_ERROR, WEBKIT_USER_CONTENT_FILTER_ERROR_INVALID_SOURCE, "Source JSON rule set cannot be empty")); >+ return; >+ } >+ >+ auto* store = WEBKIT_USER_CONTENT_FILTER_STORE(g_task_get_source_object(task.get())); >+ store->priv->store->compileContentRuleList(identifier, String::fromUTF8(sourceData, sourceSize), [task = WTFMove(task)](RefPtr<API::ContentRuleList> contentRuleList, std::error_code error) { >+ if (g_task_return_error_if_cancelled(task.get())) >+ return; >+ >+ if (error) >+ g_task_return_error(task.get(), toGError(WEBKIT_USER_CONTENT_FILTER_ERROR_INVALID_SOURCE, error)); >+ else >+ g_task_return_pointer(task.get(), webkitUserContentFilterCreate(WTFMove(contentRuleList)), reinterpret_cast<GDestroyNotify>(webkit_user_content_filter_unref)); >+ }); >+} >+ >+/** >+ * webkit_user_content_filter_store_save: >+ * @store: a #WebKitUserContentFilterStore >+ * @identifier: a string used to identify the saved filter >+ * @source: #GBytes containing the rule set in JSON format >+ * @cancellable: (allow-none): a #GCancellable or %NULL to ignore >+ * @callback: (scope async): a #GAsyncReadyCallback to call when saving is completed >+ * @user_data: (closure): the data to pass to the callback function >+ * >+ * Asynchronously save a content filter from a source rule set in the >+ * [WebKit content extesions JSON format](https://webkit.org/blog/3476/content-blockers-first-look/). >+ * >+ * The @identifier can be used afterwards to refer to the filter when using >+ * webkit_user_content_filter_store_remove() and webkit_user_content_filter_store_load(). >+ * When the @identifier has been used in the past, the new filter source will replace >+ * the one saved beforehand for the same identifier. >+ * >+ * When the operation is finished, @callback will be invoked, which then can use >+ * webkit_user_content_filter_store_save_finish() to obtain the resulting filter. >+ * >+ * Since: 2.24 >+ */ >+void webkit_user_content_filter_store_save(WebKitUserContentFilterStore* store, const gchar* identifier, GBytes* source, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData) >+{ >+ g_return_if_fail(WEBKIT_IS_USER_CONTENT_FILTER_STORE(store)); >+ g_return_if_fail(identifier); >+ g_return_if_fail(source); >+ g_return_if_fail(callback); >+ >+ GRefPtr<GTask> task = adoptGRef(g_task_new(store, cancellable, callback, userData)); >+ webkitUserContentFilterStoreSaveBytes(WTFMove(task), String::fromUTF8(identifier), GRefPtr<GBytes>(source)); >+} >+ >+/** >+ * webkit_user_content_filter_store_save_finish: >+ * @store: a #WebKitUserContentFilterStore >+ * @result: a #GAsyncResult >+ * @error: return location for error or %NULL to ignore >+ * >+ * Finishes an asynchronous filter save previously started with >+ * webkit_user_content_filter_store_save(). >+ * >+ * Returns: (transfer full): a #WebKitUserContentFilter, or %NULL if saving failed >+ * >+ * Since: 2.24 >+ */ >+WebKitUserContentFilter* webkit_user_content_filter_store_save_finish(WebKitUserContentFilterStore* store, GAsyncResult* result, GError** error) >+{ >+ g_return_val_if_fail(WEBKIT_IS_USER_CONTENT_FILTER_STORE(store), nullptr); >+ g_return_val_if_fail(result, nullptr); >+ return static_cast<WebKitUserContentFilter*>(g_task_propagate_pointer(G_TASK(result), error)); >+} >+ >+struct SaveTaskData { >+ String identifier; >+}; >+WEBKIT_DEFINE_ASYNC_DATA_STRUCT(SaveTaskData) >+ >+/** >+ * webkit_user_content_filter_store_save_from_file: >+ * @store: a #WebKitUserContentFilterStore >+ * @identifier: a string used to identify the saved filter >+ * @file: a #GFile containing the rule set in JSON format >+ * @cancellable: (allow-none): a #GCancellable or %NULL to ignore >+ * @callback: (scope async): a #GAsyncReadyCallback to call when saving is completed >+ * @user_data: (closure): the data to pass to the callback function >+ * >+ * Asynchronously save a content filter from the contents of a file, which must be >+ * native to the platform, as checked by g_file_is_native(). See >+ * webkit_user_content_filter_store_save() for more details. >+ * >+ * When the operation is finished, @callback will be invoked, which then can use >+ * webkit_user_content_filter_store_save_finish() to obtain the resulting filter. >+ * >+ * Since: 2.24 >+ */ >+void webkit_user_content_filter_store_save_from_file(WebKitUserContentFilterStore* store, const gchar* identifier, GFile* file, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData) >+{ >+ g_return_if_fail(WEBKIT_IS_USER_CONTENT_FILTER_STORE(store)); >+ g_return_if_fail(identifier); >+ g_return_if_fail(G_IS_FILE(file)); >+ g_return_if_fail(callback); >+ >+ GRefPtr<GTask> task = adoptGRef(g_task_new(store, cancellable, callback, userData)); >+ >+ // Try mapping the file in memory first, and fall-back to reading the contents if that fails. >+ if (g_file_is_native(file)) { >+ GUniquePtr<char> filePath(g_file_get_path(file)); >+ GRefPtr<GMappedFile> mappedFile = adoptGRef(g_mapped_file_new(filePath.get(), FALSE, nullptr)); >+ if (mappedFile) { >+ GRefPtr<GBytes> source = adoptGRef(g_mapped_file_get_bytes(mappedFile.get())); >+ webkitUserContentFilterStoreSaveBytes(WTFMove(task), String::fromUTF8(identifier), WTFMove(source)); >+ return; >+ } >+ } >+ >+ // Pass the identifier as task data to be used in the completion callback once the contents have been loaded. >+ SaveTaskData* data = createSaveTaskData(); >+ data->identifier = String::fromUTF8(identifier); >+ g_task_set_task_data(task.get(), data, reinterpret_cast<GDestroyNotify>(destroySaveTaskData)); >+ >+ g_file_load_contents_async(file, cancellable, [](GObject* sourceObject, GAsyncResult* result, void* userData) { >+ GRefPtr<GTask> task = adoptGRef(G_TASK(userData)); >+ if (g_task_return_error_if_cancelled(task.get())) >+ return; >+ >+ char* sourceData; >+ size_t sourceSize; >+ GUniqueOutPtr<GError> error; >+ if (g_file_load_contents_finish(G_FILE(sourceObject), result, &sourceData, &sourceSize, nullptr, &error.outPtr())) { >+ SaveTaskData* data = static_cast<SaveTaskData*>(g_task_get_task_data(task.get())); >+ webkitUserContentFilterStoreSaveBytes(WTFMove(task), WTFMove(data->identifier), GRefPtr<GBytes>(g_bytes_new_take(sourceData, sourceSize))); >+ } else >+ g_task_return_error(task.get(), error.release().release()); >+ }, task.leakRef()); >+} >+ >+/** >+ * webkit_user_content_filter_store_save_from_file_finish: >+ * @store: a #WebKitUserContentFilterStore >+ * @result: a #GAsyncResult >+ * @error: return location for error or %NULL to ignore >+ * >+ * Finishes and asynchronous filter save previously started with >+ * webkit_user_content_filter_store_save_from_file(). >+ * >+ * Returns: (transfer full): a #WebKitUserContentFilter, or %NULL if saving failed. >+ * >+ * Since: 2.24 >+ */ >+WebKitUserContentFilter* webkit_user_content_filter_store_save_from_file_finish(WebKitUserContentFilterStore* store, GAsyncResult* result, GError** error) >+{ >+ g_return_val_if_fail(WEBKIT_IS_USER_CONTENT_FILTER_STORE(store), nullptr); >+ g_return_val_if_fail(result, nullptr); >+ return static_cast<WebKitUserContentFilter*>(g_task_propagate_pointer(G_TASK(result), error)); >+} >+ >+/** >+ * webkit_user_content_filter_store_remove: >+ * @store: a #WebKitUserContentFilterStore >+ * @identifier: a filter identifier >+ * @cancellable: (allow-none): a #GCancellable or %NULL to ignore >+ * @callback: (scope async): a #GAsyncReadyCallback to call when the removal is completed >+ * @user_data: (closure): the data to pass to the callback function >+ * >+ * Asynchronously remove a content filter given its @identifier. >+ * >+ * When the operation is finished, @callback will be invoked, which then can use >+ * webkit_user_content_filter_store_remove_finish() to check whether the removal was >+ * successful. >+ * >+ * Since: 2.24 >+ */ >+void webkit_user_content_filter_store_remove(WebKitUserContentFilterStore* store, const gchar* identifier, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData) >+{ >+ g_return_if_fail(WEBKIT_IS_USER_CONTENT_FILTER_STORE(store)); >+ g_return_if_fail(identifier); >+ g_return_if_fail(callback); >+ >+ GRefPtr<GTask> task = adoptGRef(g_task_new(store, cancellable, callback, userData)); >+ store->priv->store->removeContentRuleList(String::fromUTF8(identifier), [task = WTFMove(task)](std::error_code error) { >+ if (g_task_return_error_if_cancelled(task.get())) >+ return; >+ >+ if (error) { >+ ASSERT(static_cast<API::ContentRuleListStore::Error>(error.value()) == API::ContentRuleListStore::Error::RemoveFailed); >+ g_task_return_error(task.get(), toGError(WEBKIT_USER_CONTENT_FILTER_ERROR_NOT_FOUND, error)); >+ } else >+ g_task_return_boolean(task.get(), TRUE); >+ }); >+} >+ >+/** >+ * webkit_user_content_filter_store_remove_finish: >+ * @store: a #WebKitUserContentFilterStore >+ * @result: a #GAsyncResult >+ * @error: return location for error or %NULL to ignore >+ * >+ * Finishes an asynchronous filter removal previously started with >+ * webkit_user_content_filter_store_remove(). >+ * >+ * Returns: whether the removal was successful >+ * >+ * Since: 2.24 >+ */ >+gboolean webkit_user_content_filter_store_remove_finish(WebKitUserContentFilterStore* store, GAsyncResult* result, GError** error) >+{ >+ g_return_val_if_fail(WEBKIT_IS_USER_CONTENT_FILTER_STORE(store), FALSE); >+ g_return_val_if_fail(result, FALSE); >+ return g_task_propagate_boolean(G_TASK(result), error); >+} >+ >+/** >+ * webkit_user_content_filter_store_load: >+ * @store: a #WebKitUserContentFilterStore >+ * @identifier: a filter identifier >+ * @cancellable: (allow-none): a #GCancellable or %NULL to ignore >+ * @callback: (scope async): a #GAsyncReadyCallback to call when the load is completed >+ * @user_data: (closure): the data to pass to the callback function >+ * >+ * Asynchronously load a content filter given its @identifier. The filter must have been >+ * previously stored using webkit_user_content_filter_store_save(). >+ * >+ * When the operation is finished, @callback will be invoked, which then can use >+ * webkit_user_content_filter_store_load_finish() to obtain the resulting filter. >+ * >+ * Since: 2.24 >+ */ >+void webkit_user_content_filter_store_load(WebKitUserContentFilterStore* store, const gchar* identifier, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData) >+{ >+ g_return_if_fail(WEBKIT_IS_USER_CONTENT_FILTER_STORE(store)); >+ g_return_if_fail(identifier); >+ g_return_if_fail(callback); >+ >+ GRefPtr<GTask> task = adoptGRef(g_task_new(store, cancellable, callback, userData)); >+ store->priv->store->lookupContentRuleList(String::fromUTF8(identifier), [task = WTFMove(task)](RefPtr<API::ContentRuleList> contentRuleList, std::error_code error) { >+ if (g_task_return_error_if_cancelled(task.get())) >+ return; >+ >+ if (error) { >+ ASSERT(static_cast<API::ContentRuleListStore::Error>(error.value()) == API::ContentRuleListStore::Error::LookupFailed >+ || static_cast<API::ContentRuleListStore::Error>(error.value()) == API::ContentRuleListStore::Error::VersionMismatch); >+ g_task_return_error(task.get(), toGError(WEBKIT_USER_CONTENT_FILTER_ERROR_NOT_FOUND, error)); >+ } else >+ g_task_return_pointer(task.get(), webkitUserContentFilterCreate(WTFMove(contentRuleList)), reinterpret_cast<GDestroyNotify>(webkit_user_content_filter_unref)); >+ }); >+} >+ >+/** >+ * webkit_user_content_filter_store_load_finish: >+ * @store: a #WebKitUserContentFilterStore >+ * @result: a #GAsyncResult >+ * @error: return location for error or %NULL to ignore >+ * >+ * Finishes an asynchronous filter load previously started with >+ * webkit_user_content_filter_store_load(). >+ * >+ * Returns: (transfer full): a #WebKitUserContentFilter, or %NULL if the load failed >+ * >+ * Since: 2.24 >+ */ >+WebKitUserContentFilter* webkit_user_content_filter_store_load_finish(WebKitUserContentFilterStore* store, GAsyncResult* result, GError** error) >+{ >+ g_return_val_if_fail(WEBKIT_IS_USER_CONTENT_FILTER_STORE(store), nullptr); >+ g_return_val_if_fail(result, nullptr); >+ return static_cast<WebKitUserContentFilter*>(g_task_propagate_pointer(G_TASK(result), error)); >+} >+ >+/** >+ * webkit_user_content_filter_store_fetch_identifiers: >+ * @store: a #WebKitUserContentFilterStore >+ * @cancellable: (allow-none): a #GCancellable or %NULL to ignore >+ * @callback: (scope async): a #GAsyncReadyCallback to call when the removal is completed >+ * @user_data: (closure): the data to pass to the callback function >+ * >+ * Asynchronously retrieve a list of the identifiers for all the stored filters. >+ * >+ * When the operation is finished, @callback will be invoked, which then can use >+ * webkit_user_content_filter_store_fetch_identifiers_finish() to obtain the list of >+ * filter identifiers. >+ * >+ * Since: 2.24 >+ */ >+void webkit_user_content_filter_store_fetch_identifiers(WebKitUserContentFilterStore* store, GCancellable* cancellable, GAsyncReadyCallback callback, gpointer userData) >+{ >+ g_return_if_fail(WEBKIT_IS_USER_CONTENT_FILTER_STORE(store)); >+ g_return_if_fail(callback); >+ >+ GRefPtr<GTask> task = adoptGRef(g_task_new(store, cancellable, callback, userData)); >+ store->priv->store->getAvailableContentRuleListIdentifiers([task = WTFMove(task)](WTF::Vector<WTF::String> identifiers) { >+ if (g_task_return_error_if_cancelled(task.get())) >+ return; >+ >+ GStrv result = static_cast<GStrv>(g_new0(gchar*, identifiers.size() + 1)); >+ for (size_t i = 0; i < identifiers.size(); ++i) >+ result[i] = g_strdup(identifiers[i].utf8().data()); >+ g_task_return_pointer(task.get(), result, reinterpret_cast<GDestroyNotify>(g_strfreev)); >+ }); >+} >+ >+/** >+ * webkit_user_content_filter_store_fetch_identifiers_finish: >+ * @store: a #WebKitUserContentFilterStore >+ * @result: a #GAsyncResult >+ * >+ * Finishes an asynchronous fetch of the list of identifiers for the stored filters previously >+ * started with webkit_user_content_filter_store_fetch_identifiers(). >+ * >+ * Returns: (transfer full) (array zero-terminated=1) (element-type utf8): a %NULL-terminated list of filter identifiers. >+ * >+ * Since: 2.24 >+ */ >+gchar** webkit_user_content_filter_store_fetch_identifiers_finish(WebKitUserContentFilterStore* store, GAsyncResult* result) >+{ >+ g_return_val_if_fail(WEBKIT_IS_USER_CONTENT_FILTER_STORE(store), nullptr); >+ g_return_val_if_fail(result, nullptr); >+ return static_cast<gchar**>(g_task_propagate_pointer(G_TASK(result), nullptr)); >+} >diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUserContentManager.cpp b/Source/WebKit/UIProcess/API/glib/WebKitUserContentManager.cpp >index 7b0769470981c90cf29a305c3216525937af537b..48b38eac08d912c9639ef55094b10f1ffad1d9f9 100644 >--- a/Source/WebKit/UIProcess/API/glib/WebKitUserContentManager.cpp >+++ b/Source/WebKit/UIProcess/API/glib/WebKitUserContentManager.cpp >@@ -318,6 +318,56 @@ void webkit_user_content_manager_unregister_script_message_handler_in_world(WebK > manager->priv->userContentController->removeUserMessageHandlerForName(String::fromUTF8(name), webkitUserContentWorld(worldName)); > } > >+/** >+ * webkit_user_content_manager_add_filter: >+ * @manager: A #WebKitUserContentManager >+ * @filter: A #WebKitUserContentFilter >+ * >+ * Adds a #WebKitUserContentFilter to the given #WebKitUserContentManager. >+ * The same #WebKitUserContentFilter can be reused with multiple >+ * #WebKitUserContentManager instances. >+ * >+ * Filters need to be saved and loaded from #WebKitUserContentFilterStore. >+ * >+ * Since: 2.24 >+ */ >+void webkit_user_content_manager_add_filter(WebKitUserContentManager* manager, WebKitUserContentFilter* filter) >+{ >+ g_return_if_fail(WEBKIT_IS_USER_CONTENT_MANAGER(manager)); >+ g_return_if_fail(filter); >+ manager->priv->userContentController->addContentRuleList(webkitUserContentFilterGetContentRuleList(filter)); >+} >+ >+/** >+ * webkit_user_content_manager_remove_filter: >+ * @manager: A #WebKitUserContentManager >+ * @filter: A #WebKitUserContentFilter >+ * >+ * Removes a filter from the given #WebKitUserContentManager. >+ * >+ * Since 2.24 >+ */ >+void webkit_user_content_manager_remove_filter(WebKitUserContentManager* manager, WebKitUserContentFilter* filter) >+{ >+ g_return_if_fail(WEBKIT_IS_USER_CONTENT_MANAGER(manager)); >+ g_return_if_fail(filter); >+ manager->priv->userContentController->removeContentRuleList(webkitUserContentFilterGetContentRuleList(filter).name()); >+} >+ >+/** >+ * webkit_user_content_manager_remove_all_filters: >+ * @manager: A #WebKitUserContentManager >+ * >+ * Removes all content filters from the given #WebKitUserContentManager. >+ * >+ * Since: 2.24 >+ */ >+void webkit_user_content_manager_remove_all_filters(WebKitUserContentManager* manager) >+{ >+ g_return_if_fail(WEBKIT_IS_USER_CONTENT_MANAGER(manager)); >+ manager->priv->userContentController->removeAllContentRuleLists(); >+} >+ > WebUserContentControllerProxy* webkitUserContentManagerGetUserContentControllerProxy(WebKitUserContentManager* manager) > { > return manager->priv->userContentController.get(); >diff --git a/Source/WebKit/UIProcess/API/glib/WebKitUserContentPrivate.h b/Source/WebKit/UIProcess/API/glib/WebKitUserContentPrivate.h >index f181a294553cb28ff8dca95b4fc16aca88ce31b7..ad3495bb8404a5074fcdf80e75d49bacdce2509e 100644 >--- a/Source/WebKit/UIProcess/API/glib/WebKitUserContentPrivate.h >+++ b/Source/WebKit/UIProcess/API/glib/WebKitUserContentPrivate.h >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2014 Igalia S.L. >+ * Copyright (C) 2014, 2018 Igalia S.L. > * > * This library is free software; you can redistribute it and/or > * modify it under the terms of the GNU Library General Public >@@ -20,6 +20,7 @@ > #ifndef WebKitUserContentPrivate_h > #define WebKitUserContentPrivate_h > >+#include "APIContentRuleList.h" > #include "APIUserContentWorld.h" > #include "APIUserScript.h" > #include "APIUserStyleSheet.h" >@@ -30,5 +31,7 @@ > API::UserScript& webkitUserScriptGetUserScript(WebKitUserScript*); > API::UserStyleSheet& webkitUserStyleSheetGetUserStyleSheet(WebKitUserStyleSheet*); > API::UserContentWorld& webkitUserContentWorld(const char*); >+API::ContentRuleList& webkitUserContentFilterGetContentRuleList(WebKitUserContentFilter*); >+WebKitUserContentFilter* webkitUserContentFilterCreate(RefPtr<API::ContentRuleList>&&); > > #endif // WebKitUserContentPrivate_h >diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitAutocleanups.h b/Source/WebKit/UIProcess/API/gtk/WebKitAutocleanups.h >index 8cc9f0f77622130342f70eab5f4bf2cf1ab7720f..ed7eda7520120fda02cd0332455a193520a4d1f4 100644 >--- a/Source/WebKit/UIProcess/API/gtk/WebKitAutocleanups.h >+++ b/Source/WebKit/UIProcess/API/gtk/WebKitAutocleanups.h >@@ -65,6 +65,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitSettings, g_object_unref) > G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitURIRequest, g_object_unref) > G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitURIResponse, g_object_unref) > G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitURISchemeRequest, g_object_unref) >+G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitUserContentFilterStore, g_object_unref) > G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitUserContentManager, g_object_unref) > G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitUserMediaPermissionRequest, g_object_unref) > G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitWebContext, g_object_unref) >@@ -83,6 +84,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitNetworkProxySettings, webkit_network_proxy_ > G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitSecurityOrigin, webkit_security_origin_unref) > G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitUserScript, webkit_user_script_unref) > G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitUserStyleSheet, webkit_user_style_sheet_unref) >+G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitUserContentFilter, webkit_user_content_filter_unref) > G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitWebsiteData, webkit_website_data_unref) > G_DEFINE_AUTOPTR_CLEANUP_FUNC (WebKitWebViewSessionState, webkit_web_view_session_state_unref) > >diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitError.h b/Source/WebKit/UIProcess/API/gtk/WebKitError.h >index 78b8ddcb8a7ca4fa271524e95692cfe2a5bbb874..29d4f7c7fac8d0a444cab85fbdddde5d020e3dd9 100644 >--- a/Source/WebKit/UIProcess/API/gtk/WebKitError.h >+++ b/Source/WebKit/UIProcess/API/gtk/WebKitError.h >@@ -29,13 +29,14 @@ > > G_BEGIN_DECLS > >-#define WEBKIT_NETWORK_ERROR webkit_network_error_quark () >-#define WEBKIT_POLICY_ERROR webkit_policy_error_quark () >-#define WEBKIT_PLUGIN_ERROR webkit_plugin_error_quark () >-#define WEBKIT_DOWNLOAD_ERROR webkit_download_error_quark () >-#define WEBKIT_PRINT_ERROR webkit_print_error_quark () >-#define WEBKIT_JAVASCRIPT_ERROR webkit_javascript_error_quark () >-#define WEBKIT_SNAPSHOT_ERROR webkit_snapshot_error_quark () >+#define WEBKIT_NETWORK_ERROR webkit_network_error_quark () >+#define WEBKIT_POLICY_ERROR webkit_policy_error_quark () >+#define WEBKIT_PLUGIN_ERROR webkit_plugin_error_quark () >+#define WEBKIT_DOWNLOAD_ERROR webkit_download_error_quark () >+#define WEBKIT_PRINT_ERROR webkit_print_error_quark () >+#define WEBKIT_JAVASCRIPT_ERROR webkit_javascript_error_quark () >+#define WEBKIT_SNAPSHOT_ERROR webkit_snapshot_error_quark () >+#define WEBKIT_USER_CONTENT_FILTER_ERROR webkit_user_content_filter_error_quark () > > /** > * WebKitNetworkError: >@@ -141,26 +142,41 @@ typedef enum { > WEBKIT_SNAPSHOT_ERROR_FAILED_TO_CREATE = 799 > } WebKitSnapshotError; > >+/** >+ * WebKitUserContentFilterError: >+ * @WEBKIT_USER_CONTENT_FILTER_ERROR_INVALID_SOURCE: The JSON source for a content filter is invalid. >+ * @WEBKIT_USER_CONTENT_FILTER_ERROR_NOT_FOUND: The requested content filter could not be found. >+ * >+ * Since: 2.24 >+ */ >+typedef enum { >+ WEBKIT_USER_CONTENT_FILTER_ERROR_INVALID_SOURCE, >+ WEBKIT_USER_CONTENT_FILTER_ERROR_NOT_FOUND, >+} WebKitUserContentFilterError; >+ >+WEBKIT_API GQuark >+webkit_network_error_quark (void); >+ > WEBKIT_API GQuark >-webkit_network_error_quark (void); >+webkit_policy_error_quark (void); > > WEBKIT_API GQuark >-webkit_policy_error_quark (void); >+webkit_plugin_error_quark (void); > > WEBKIT_API GQuark >-webkit_plugin_error_quark (void); >+webkit_download_error_quark (void); > > WEBKIT_API GQuark >-webkit_download_error_quark (void); >+webkit_print_error_quark (void); > > WEBKIT_API GQuark >-webkit_print_error_quark (void); >+webkit_javascript_error_quark (void); > > WEBKIT_API GQuark >-webkit_javascript_error_quark (void); >+webkit_snapshot_error_quark (void); > > WEBKIT_API GQuark >-webkit_snapshot_error_quark (void); >+webkit_user_content_filter_error_quark (void); > > G_END_DECLS > >diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitUserContent.h b/Source/WebKit/UIProcess/API/gtk/WebKitUserContent.h >index 1dd450d0cb7290f25cbb4ce67a4a7ad1f1d3d1f3..2746e763f03a0803a72bbf7fda5bdda46edc6e52 100644 >--- a/Source/WebKit/UIProcess/API/gtk/WebKitUserContent.h >+++ b/Source/WebKit/UIProcess/API/gtk/WebKitUserContent.h >@@ -136,6 +136,22 @@ webkit_user_script_new_for_world (const gchar *source, > const gchar* const *whitelist, > const gchar* const *blacklist); > >+#define WEBKIT_TYPE_USER_CONTENT_FILTER (webkit_user_content_filter_get_type()) >+ >+typedef struct _WebKitUserContentFilter WebKitUserContentFilter; >+ >+WEBKIT_API GType >+webkit_user_content_filter_get_type (void); >+ >+WEBKIT_API const char* >+webkit_user_content_filter_get_identifier (WebKitUserContentFilter *user_content_filter); >+ >+WEBKIT_API WebKitUserContentFilter * >+webkit_user_content_filter_ref (WebKitUserContentFilter *user_content_filter); >+ >+WEBKIT_API void >+webkit_user_content_filter_unref (WebKitUserContentFilter *user_content_filter); >+ > G_END_DECLS > > #endif >diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitUserContentFilterStore.h b/Source/WebKit/UIProcess/API/gtk/WebKitUserContentFilterStore.h >new file mode 100644 >index 0000000000000000000000000000000000000000..3cab886c04e6b4eba54f695dab57cafdeb94ccbe >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/gtk/WebKitUserContentFilterStore.h >@@ -0,0 +1,139 @@ >+/* >+ * Copyright (C) 2018 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#if !defined(__WEBKIT2_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) >+#error "Only <webkit2/webkit2.h> can be included directly." >+#endif >+ >+#ifndef WebKitUserContentFilterStore_h >+#define WebKitUserContentFilterStore_h >+ >+#include <gio/gio.h> >+#include <webkit2/WebKitDefines.h> >+ >+G_BEGIN_DECLS >+ >+#define WEBKIT_TYPE_USER_CONTENT_FILTER_STORE (webkit_user_content_filter_store_get_type()) >+#define WEBKIT_USER_CONTENT_FILTER_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_USER_CONTENT_FILTER_STORE, WebKitUserContentFilterStore)) >+#define WEBKIT_IS_USER_CONTENT_FILTER_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_USER_CONTENT_FILTER_STORE)) >+#define WEBKIT_USER_CONTENT_FILTER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_USER_CONTENT_FILTER_STORE, WebKitUserContentFilterStoreClass)) >+#define WEBKIT_IS_USER_CONTENT_FILTER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_USER_CONTENT_FILTER_STORE)) >+#define WEBKIT_USER_CONTENT_FILTER_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_USER_CONTENT_FILTER_STORE, WebKitUserContentFilterStoreClass)) >+ >+typedef struct _WebKitUserContentFilterStore WebKitUserContentFilterStore; >+typedef struct _WebKitUserContentFilterStoreClass WebKitUserContentFilterStoreClass; >+typedef struct _WebKitUserContentFilterStorePrivate WebKitUserContentFilterStorePrivate; >+ >+typedef struct _WebKitUserContentFilter WebKitUserContentFilter; >+ >+struct _WebKitUserContentFilterStore { >+ GObject parent; >+ >+ /*< private >*/ >+ WebKitUserContentFilterStorePrivate *priv; >+}; >+ >+struct _WebKitUserContentFilterStoreClass { >+ GObjectClass parent_class; >+ >+ void (*_webkit_reserved0) (void); >+ void (*_webkit_reserved1) (void); >+ void (*_webkit_reserved2) (void); >+ void (*_webkit_reserved3) (void); >+}; >+ >+ >+WEBKIT_API GType >+webkit_user_content_filter_store_get_type (void); >+ >+WEBKIT_API WebKitUserContentFilterStore * >+webkit_user_content_filter_store_new (const gchar *storage_path); >+ >+WEBKIT_API const gchar * >+webkit_user_content_filter_store_get_path (WebKitUserContentFilterStore *store); >+ >+WEBKIT_API void >+webkit_user_content_filter_store_save (WebKitUserContentFilterStore *store, >+ const gchar *identifier, >+ GBytes *source, >+ GCancellable *cancellable, >+ GAsyncReadyCallback callback, >+ gpointer user_data); >+ >+WEBKIT_API WebKitUserContentFilter * >+webkit_user_content_filter_store_save_finish (WebKitUserContentFilterStore *store, >+ GAsyncResult *result, >+ GError **error); >+ >+WEBKIT_API void >+webkit_user_content_filter_store_save_from_file (WebKitUserContentFilterStore *store, >+ const gchar *identifier, >+ GFile *file, >+ GCancellable *cancellable, >+ GAsyncReadyCallback callback, >+ gpointer user_data); >+ >+WEBKIT_API WebKitUserContentFilter * >+webkit_user_content_filter_store_save_from_file_finish (WebKitUserContentFilterStore *store, >+ GAsyncResult *result, >+ GError **error); >+ >+WEBKIT_API void >+webkit_user_content_filter_store_remove (WebKitUserContentFilterStore *store, >+ const gchar *identifier, >+ GCancellable *cancellable, >+ GAsyncReadyCallback callback, >+ gpointer user_data); >+ >+WEBKIT_API gboolean >+webkit_user_content_filter_store_remove_finish (WebKitUserContentFilterStore *store, >+ GAsyncResult *result, >+ GError **error); >+ >+WEBKIT_API void >+webkit_user_content_filter_store_load (WebKitUserContentFilterStore *store, >+ const gchar *identifier, >+ GCancellable *cancellable, >+ GAsyncReadyCallback callback, >+ gpointer user_data); >+ >+WEBKIT_API WebKitUserContentFilter * >+webkit_user_content_filter_store_load_finish (WebKitUserContentFilterStore *store, >+ GAsyncResult *result, >+ GError **error); >+ >+WEBKIT_API void >+webkit_user_content_filter_store_fetch_identifiers (WebKitUserContentFilterStore *store, >+ GCancellable *cancellable, >+ GAsyncReadyCallback callback, >+ gpointer user_data); >+ >+WEBKIT_API gchar** >+webkit_user_content_filter_store_fetch_identifiers_finish (WebKitUserContentFilterStore *store, >+ GAsyncResult *result); >+ >+G_END_DECLS >+ >+#endif /* !WebKitUserContentFilterStore_h */ >diff --git a/Source/WebKit/UIProcess/API/gtk/WebKitUserContentManager.h b/Source/WebKit/UIProcess/API/gtk/WebKitUserContentManager.h >index ff505689323ab8b514ed387fcadbc3952fb313e5..1f41d1191386893f68ee865b40802316db810246 100644 >--- a/Source/WebKit/UIProcess/API/gtk/WebKitUserContentManager.h >+++ b/Source/WebKit/UIProcess/API/gtk/WebKitUserContentManager.h >@@ -93,6 +93,17 @@ webkit_user_content_manager_add_script (WebKitUs > WEBKIT_API void > webkit_user_content_manager_remove_all_scripts (WebKitUserContentManager *manager); > >+WEBKIT_API void >+webkit_user_content_manager_add_filter (WebKitUserContentManager *manager, >+ WebKitUserContentFilter *filter); >+ >+WEBKIT_API void >+webkit_user_content_manager_remove_filter (WebKitUserContentManager *manager, >+ WebKitUserContentFilter *filter); >+ >+WEBKIT_API void >+webkit_user_content_manager_remove_all_filters (WebKitUserContentManager *manager); >+ > G_END_DECLS > > #endif >diff --git a/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt b/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt >index 4efb952584672511ee95d062a96e7ff4ea33fb10..06d74507f9d191aef5436865d5a0d05d6c70a37b 100644 >--- a/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt >+++ b/Source/WebKit/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt >@@ -96,6 +96,7 @@ WebKitUserScript > WebKitUserContentInjectedFrames > WebKitUserStyleLevel > WebKitUserScriptInjectionTime >+WebKitUserContentFilter > webkit_user_style_sheet_ref > webkit_user_style_sheet_unref > webkit_user_style_sheet_new >@@ -104,14 +105,19 @@ webkit_user_script_ref > webkit_user_script_unref > webkit_user_script_new > webkit_user_script_new_for_world >+webkit_user_content_filter_ref >+webkit_user_content_filter_unref >+webkit_user_content_filter_get_identifier > > <SUBSECTION Standard> > WEBKIT_TYPE_USER_STYLE_SHEET > WEBKIT_TYPE_USER_SCRIPT >+WEBKIT_TYPE_USER_CONTENT_FILTER > > <SUBSECTION Private> > webkit_user_style_sheet_get_type > webkit_user_script_get_type >+webkit_user_content_filter_get_type > </SECTION> > > <SECTION> >@@ -127,6 +133,9 @@ webkit_user_content_manager_register_script_message_handler > webkit_user_content_manager_unregister_script_message_handler > webkit_user_content_manager_register_script_message_handler_in_world > webkit_user_content_manager_unregister_script_message_handler_in_world >+webkit_user_content_manager_add_filter >+webkit_user_content_manager_remove_filter >+webkit_user_content_manager_remove_all_filters > > <SUBSECTION Standard> > WEBKIT_IS_USER_CONTENT_MANAGER >@@ -142,6 +151,37 @@ WebKitUserContentManagerPrivate > webkit_user_content_manager_get_type > </SECTION> > >+<SECTION> >+<FILE>WebKitUserContentFilterStore</FILE> >+<TITLE>WebKitUserContentFilterStore</TITLE> >+WebKitUserContentFilterStore >+webkit_user_content_filter_store_new >+webkit_user_content_filter_store_get_path >+webkit_user_content_filter_store_save >+webkit_user_content_filter_store_save_finish >+webkit_user_content_filter_store_save_from_file >+webkit_user_content_filter_store_save_from_file_finish >+webkit_user_content_filter_store_load >+webkit_user_content_filter_store_load_finish >+webkit_user_content_filter_store_remove >+webkit_user_content_filter_store_remove_finish >+webkit_user_content_filter_store_fetch_identifiers >+webkit_user_content_filter_store_fetch_identifiers_finish >+ >+<SUBSECTION Standard> >+WEBKIT_IS_USER_CONTENT_FILTER_STORE >+WEBKIT_IS_USER_CONTENT_FILTER_STORE_CLASS >+WEBKIT_TYPE_USER_CONTENT_FILTER_STORE >+WEBKIT_USER_CONTENT_FILTER_STORE >+WEBKIT_USER_CONTENT_FILTER_STORE_CLASS >+WEBKIT_USER_CONTENT_FILTER_STORE_GET_CLASS >+WebKitUserContentFilterStoreClass >+ >+<SUBSECTION Private> >+WebKitUserContentFilterStorePrivate >+webkit_user_content_filter_store_get_type >+</SECTION> >+ > <SECTION> > <FILE>WebKitWebView</FILE> > <TITLE>WebKitWebView</TITLE> >@@ -944,6 +984,7 @@ WEBKIT_DOWNLOAD_ERROR > WEBKIT_PRINT_ERROR > WEBKIT_JAVASCRIPT_ERROR > WEBKIT_SNAPSHOT_ERROR >+WEBKIT_USER_CONTENT_FILTER_ERROR > WebKitNetworkError > WebKitPluginError > WebKitPolicyError >@@ -951,6 +992,7 @@ WebKitDownloadError > WebKitPrintError > WebKitJavascriptError > WebKitSnapshotError >+WebKitUserContentFilterError > webkit_network_error_quark > webkit_plugin_error_quark > webkit_policy_error_quark >@@ -958,6 +1000,7 @@ webkit_download_error_quark > webkit_print_error_quark > webkit_javascript_error_quark > webkit_snapshot_error_quark >+webkit_user_content_filter_error_quark > </SECTION> > > <SECTION> >diff --git a/Source/WebKit/UIProcess/API/gtk/webkit2.h b/Source/WebKit/UIProcess/API/gtk/webkit2.h >index 5c6e4ccec5aba1a29bae15561ac06102a6f0079e..1470b2753463e31aef860379460316dc4839b06f 100644 >--- a/Source/WebKit/UIProcess/API/gtk/webkit2.h >+++ b/Source/WebKit/UIProcess/API/gtk/webkit2.h >@@ -75,6 +75,7 @@ > #include <webkit2/WebKitURISchemeRequest.h> > #include <webkit2/WebKitURIUtilities.h> > #include <webkit2/WebKitUserContent.h> >+#include <webkit2/WebKitUserContentFilterStore.h> > #include <webkit2/WebKitUserContentManager.h> > #include <webkit2/WebKitUserMediaPermissionRequest.h> > #include <webkit2/WebKitVersion.h> >diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitError.h b/Source/WebKit/UIProcess/API/wpe/WebKitError.h >index 4dad4ef3d1f7c3a6399cd50b6f213e91213fc814..5e4e8fa5a6f4c1ff6246910bb5d4ab3268740661 100644 >--- a/Source/WebKit/UIProcess/API/wpe/WebKitError.h >+++ b/Source/WebKit/UIProcess/API/wpe/WebKitError.h >@@ -29,12 +29,13 @@ > > G_BEGIN_DECLS > >-#define WEBKIT_NETWORK_ERROR webkit_network_error_quark () >-#define WEBKIT_POLICY_ERROR webkit_policy_error_quark () >-#define WEBKIT_PLUGIN_ERROR webkit_plugin_error_quark () >-#define WEBKIT_DOWNLOAD_ERROR webkit_download_error_quark () >-#define WEBKIT_JAVASCRIPT_ERROR webkit_javascript_error_quark () >-#define WEBKIT_SNAPSHOT_ERROR webkit_snapshot_error_quark () >+#define WEBKIT_NETWORK_ERROR webkit_network_error_quark () >+#define WEBKIT_POLICY_ERROR webkit_policy_error_quark () >+#define WEBKIT_PLUGIN_ERROR webkit_plugin_error_quark () >+#define WEBKIT_DOWNLOAD_ERROR webkit_download_error_quark () >+#define WEBKIT_JAVASCRIPT_ERROR webkit_javascript_error_quark () >+#define WEBKIT_SNAPSHOT_ERROR webkit_snapshot_error_quark () >+#define WEBKIT_USER_CONTENT_FILTER_ERROR webkit_user_content_filter_error_quark () > > /** > * WebKitNetworkError: >@@ -126,23 +127,38 @@ typedef enum { > WEBKIT_SNAPSHOT_ERROR_FAILED_TO_CREATE = 799 > } WebKitSnapshotError; > >+/** >+ * WebKitUserContentFilterError: >+ * @WEBKIT_USER_CONTENT_FILTER_ERROR_INVALID_SOURCE: The JSON source for a content filter is invalid. >+ * @WEBKIT_USER_CONTENT_FILTER_ERROR_NOT_FOUND: The requested content filter could not be found. >+ * >+ * Since: 2.24 >+ */ >+typedef enum { >+ WEBKIT_USER_CONTENT_FILTER_ERROR_INVALID_SOURCE, >+ WEBKIT_USER_CONTENT_FILTER_ERROR_NOT_FOUND, >+} WebKitUserContentFilterError; >+ >+WEBKIT_API GQuark >+webkit_network_error_quark (void); >+ > WEBKIT_API GQuark >-webkit_network_error_quark (void); >+webkit_policy_error_quark (void); > > WEBKIT_API GQuark >-webkit_policy_error_quark (void); >+webkit_plugin_error_quark (void); > > WEBKIT_API GQuark >-webkit_plugin_error_quark (void); >+webkit_download_error_quark (void); > > WEBKIT_API GQuark >-webkit_download_error_quark (void); >+webkit_javascript_error_quark (void); > > WEBKIT_API GQuark >-webkit_javascript_error_quark (void); >+webkit_snapshot_error_quark (void); > > WEBKIT_API GQuark >-webkit_snapshot_error_quark (void); >+webkit_user_content_filter_error_quark (void); > > G_END_DECLS > >diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitUserContent.h b/Source/WebKit/UIProcess/API/wpe/WebKitUserContent.h >index 926f98dc5ad899c33e3a134189f59b921d8e8f10..f28b99a1d547c764646d6a3b77149cfba5a7a771 100644 >--- a/Source/WebKit/UIProcess/API/wpe/WebKitUserContent.h >+++ b/Source/WebKit/UIProcess/API/wpe/WebKitUserContent.h >@@ -136,6 +136,22 @@ webkit_user_script_new_for_world (const gchar *source, > const gchar* const *whitelist, > const gchar* const *blacklist); > >+#define WEBKIT_TYPE_USER_CONTENT_FILTER (webkit_user_content_filter_get_type()) >+ >+typedef struct _WebKitUserContentFilter WebKitUserContentFilter; >+ >+WEBKIT_API GType >+webkit_user_content_filter_get_type (void); >+ >+WEBKIT_API const char* >+webkit_user_content_filter_get_identifier (WebKitUserContentFilter *user_content_filter); >+ >+WEBKIT_API WebKitUserContentFilter * >+webkit_user_content_filter_ref (WebKitUserContentFilter *user_content_filter); >+ >+WEBKIT_API void >+webkit_user_content_filter_unref (WebKitUserContentFilter *user_content_filter); >+ > G_END_DECLS > > #endif >diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitUserContentFilterStore.h b/Source/WebKit/UIProcess/API/wpe/WebKitUserContentFilterStore.h >new file mode 100644 >index 0000000000000000000000000000000000000000..9b760feb0eb050b422083cc136883c0012439ebb >--- /dev/null >+++ b/Source/WebKit/UIProcess/API/wpe/WebKitUserContentFilterStore.h >@@ -0,0 +1,139 @@ >+/* >+ * Copyright (C) 2018 Igalia S.L. >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >+ * THE POSSIBILITY OF SUCH DAMAGE. >+ */ >+ >+#if !defined(__WEBKIT_H_INSIDE__) && !defined(WEBKIT2_COMPILATION) >+#error "Only <wpe/webkit.h> can be included directly." >+#endif >+ >+#ifndef WebKitUserContentFilterStore_h >+#define WebKitUserContentFilterStore_h >+ >+#include <gio/gio.h> >+#include <wpe/WebKitDefines.h> >+ >+G_BEGIN_DECLS >+ >+#define WEBKIT_TYPE_USER_CONTENT_FILTER_STORE (webkit_user_content_filter_store_get_type()) >+#define WEBKIT_USER_CONTENT_FILTER_STORE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_USER_CONTENT_FILTER_STORE, WebKitUserContentFilterStore)) >+#define WEBKIT_IS_USER_CONTENT_FILTER_STORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_USER_CONTENT_FILTER_STORE)) >+#define WEBKIT_USER_CONTENT_FILTER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), WEBKIT_TYPE_USER_CONTENT_FILTER_STORE, WebKitUserContentFilterStoreClass)) >+#define WEBKIT_IS_USER_CONTENT_FILTER_STORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), WEBKIT_TYPE_USER_CONTENT_FILTER_STORE)) >+#define WEBKIT_USER_CONTENT_FILTER_STORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), WEBKIT_TYPE_USER_CONTENT_FILTER_STORE, WebKitUserContentFilterStoreClass)) >+ >+typedef struct _WebKitUserContentFilterStore WebKitUserContentFilterStore; >+typedef struct _WebKitUserContentFilterStoreClass WebKitUserContentFilterStoreClass; >+typedef struct _WebKitUserContentFilterStorePrivate WebKitUserContentFilterStorePrivate; >+ >+typedef struct _WebKitUserContentFilter WebKitUserContentFilter; >+ >+struct _WebKitUserContentFilterStore { >+ GObject parent; >+ >+ /*< private >*/ >+ WebKitUserContentFilterStorePrivate *priv; >+}; >+ >+struct _WebKitUserContentFilterStoreClass { >+ GObjectClass parent_class; >+ >+ void (*_webkit_reserved0) (void); >+ void (*_webkit_reserved1) (void); >+ void (*_webkit_reserved2) (void); >+ void (*_webkit_reserved3) (void); >+}; >+ >+ >+WEBKIT_API GType >+webkit_user_content_filter_store_get_type (void); >+ >+WEBKIT_API WebKitUserContentFilterStore * >+webkit_user_content_filter_store_new (const gchar *storage_path); >+ >+WEBKIT_API const gchar * >+webkit_user_content_filter_store_get_path (WebKitUserContentFilterStore *store); >+ >+WEBKIT_API void >+webkit_user_content_filter_store_save (WebKitUserContentFilterStore *store, >+ const gchar *identifier, >+ GBytes *source, >+ GCancellable *cancellable, >+ GAsyncReadyCallback callback, >+ gpointer user_data); >+ >+WEBKIT_API WebKitUserContentFilter * >+webkit_user_content_filter_store_save_finish (WebKitUserContentFilterStore *store, >+ GAsyncResult *result, >+ GError **error); >+ >+WEBKIT_API void >+webkit_user_content_filter_store_save_from_file (WebKitUserContentFilterStore *store, >+ const gchar *identifier, >+ GFile *file, >+ GCancellable *cancellable, >+ GAsyncReadyCallback callback, >+ gpointer user_data); >+ >+WEBKIT_API WebKitUserContentFilter * >+webkit_user_content_filter_store_save_from_file_finish (WebKitUserContentFilterStore *store, >+ GAsyncResult *result, >+ GError **error); >+ >+WEBKIT_API void >+webkit_user_content_filter_store_remove (WebKitUserContentFilterStore *store, >+ const gchar *identifier, >+ GCancellable *cancellable, >+ GAsyncReadyCallback callback, >+ gpointer user_data); >+ >+WEBKIT_API gboolean >+webkit_user_content_filter_store_remove_finish (WebKitUserContentFilterStore *store, >+ GAsyncResult *result, >+ GError **error); >+ >+WEBKIT_API void >+webkit_user_content_filter_store_load (WebKitUserContentFilterStore *store, >+ const gchar *identifier, >+ GCancellable *cancellable, >+ GAsyncReadyCallback callback, >+ gpointer user_data); >+ >+WEBKIT_API WebKitUserContentFilter * >+webkit_user_content_filter_store_load_finish (WebKitUserContentFilterStore *store, >+ GAsyncResult *result, >+ GError **error); >+ >+WEBKIT_API void >+webkit_user_content_filter_store_fetch_identifiers (WebKitUserContentFilterStore *store, >+ GCancellable *cancellable, >+ GAsyncReadyCallback callback, >+ gpointer user_data); >+ >+WEBKIT_API gchar** >+webkit_user_content_filter_store_fetch_identifiers_finish (WebKitUserContentFilterStore *store, >+ GAsyncResult *result); >+ >+G_END_DECLS >+ >+#endif /* !WebKitUserContentFilterStore_h */ >diff --git a/Source/WebKit/UIProcess/API/wpe/WebKitUserContentManager.h b/Source/WebKit/UIProcess/API/wpe/WebKitUserContentManager.h >index 6513fa7b4235eebac361b94d65c68947d85916a3..12d7ede6ec468ed26ddb2689541f77e56abe77aa 100644 >--- a/Source/WebKit/UIProcess/API/wpe/WebKitUserContentManager.h >+++ b/Source/WebKit/UIProcess/API/wpe/WebKitUserContentManager.h >@@ -93,6 +93,17 @@ webkit_user_content_manager_add_script (WebKitUs > WEBKIT_API void > webkit_user_content_manager_remove_all_scripts (WebKitUserContentManager *manager); > >+WEBKIT_API void >+webkit_user_content_manager_add_filter (WebKitUserContentManager *manager, >+ WebKitUserContentFilter *filter); >+ >+WEBKIT_API void >+webkit_user_content_manager_remove_filter (WebKitUserContentManager *manager, >+ WebKitUserContentFilter *filter); >+ >+WEBKIT_API void >+webkit_user_content_manager_remove_all_filters (WebKitUserContentManager *manager); >+ > G_END_DECLS > > #endif >diff --git a/Source/WebKit/UIProcess/API/wpe/docs/wpe-0.1-sections.txt b/Source/WebKit/UIProcess/API/wpe/docs/wpe-0.1-sections.txt >index a5ecfe4637f8f3917af26127face01517f378806..eae29cb4f9fac20a78cc47d0efe24181b6185148 100644 >--- a/Source/WebKit/UIProcess/API/wpe/docs/wpe-0.1-sections.txt >+++ b/Source/WebKit/UIProcess/API/wpe/docs/wpe-0.1-sections.txt >@@ -73,6 +73,7 @@ WebKitUserScript > WebKitUserContentInjectedFrames > WebKitUserStyleLevel > WebKitUserScriptInjectionTime >+WebKitUserContentFilter > webkit_user_style_sheet_ref > webkit_user_style_sheet_unref > webkit_user_style_sheet_new >@@ -81,14 +82,19 @@ webkit_user_script_ref > webkit_user_script_unref > webkit_user_script_new > webkit_user_script_new_for_world >+webkit_user_content_filter_ref >+webkit_user_content_filter_unref >+webkit_user_content_filter_get_identifier > > <SUBSECTION Standard> > WEBKIT_TYPE_USER_STYLE_SHEET > WEBKIT_TYPE_USER_SCRIPT >+WEBKIT_TYPE_USER_CONTENT_FILTER > > <SUBSECTION Private> > webkit_user_style_sheet_get_type > webkit_user_script_get_type >+webkit_user_content_filter_get_type > </SECTION> > > <SECTION> >@@ -104,6 +110,9 @@ webkit_user_content_manager_register_script_message_handler > webkit_user_content_manager_unregister_script_message_handler > webkit_user_content_manager_register_script_message_handler_in_world > webkit_user_content_manager_unregister_script_message_handler_in_world >+webkit_user_content_manager_add_filter >+webkit_user_content_manager_remove_filter >+webkit_user_content_manager_remove_all_filters > > <SUBSECTION Standard> > WEBKIT_IS_USER_CONTENT_MANAGER >@@ -119,6 +128,37 @@ WebKitUserContentManagerPrivate > webkit_user_content_manager_get_type > </SECTION> > >+<SECTION> >+<FILE>WebKitUserContentFilterStore</FILE> >+<TITLE>WebKitUserContentFilterStore</TITLE> >+WebKitUserContentFilterStore >+webkit_user_content_filter_store_new >+webkit_user_content_filter_store_get_path >+webkit_user_content_filter_store_save >+webkit_user_content_filter_store_save_finish >+webkit_user_content_filter_store_save_from_file >+webkit_user_content_filter_store_save_from_file_finish >+webkit_user_content_filter_store_load >+webkit_user_content_filter_store_load_finish >+webkit_user_content_filter_store_remove >+webkit_user_content_filter_store_remove_finish >+webkit_user_content_filter_store_fetch_identifiers >+webkit_user_content_filter_store_fetch_identifiers_finish >+ >+<SUBSECTION Standard> >+WEBKIT_IS_USER_CONTENT_FILTER_STORE >+WEBKIT_IS_USER_CONTENT_FILTER_STORE_CLASS >+WEBKIT_TYPE_USER_CONTENT_FILTER_STORE >+WEBKIT_USER_CONTENT_FILTER_STORE >+WEBKIT_USER_CONTENT_FILTER_STORE_CLASS >+WEBKIT_USER_CONTENT_FILTER_STORE_GET_CLASS >+WebKitUserContentFilterStoreClass >+ >+<SUBSECTION Private> >+WebKitUserContentFilterStorePrivate >+webkit_user_content_filter_store_get_type >+</SECTION> >+ > <SECTION> > <FILE>WebKitWebView</FILE> > <TITLE>WebKitWebView</TITLE> >@@ -887,18 +927,21 @@ WEBKIT_POLICY_ERROR > WEBKIT_DOWNLOAD_ERROR > WEBKIT_JAVASCRIPT_ERROR > WEBKIT_SNAPSHOT_ERROR >+WEBKIT_USER_CONTENT_FILTER_ERROR > WebKitNetworkError > WebKitPluginError > WebKitPolicyError > WebKitDownloadError > WebKitJavascriptError > WebKitSnapshotError >+WebKitUserContentFilterError > webkit_network_error_quark > webkit_plugin_error_quark > webkit_policy_error_quark > webkit_download_error_quark > webkit_javascript_error_quark > webkit_snapshot_error_quark >+webkit_user_content_filter_error_quark > </SECTION> > > <SECTION> >diff --git a/Source/WebKit/UIProcess/API/wpe/webkit.h b/Source/WebKit/UIProcess/API/wpe/webkit.h >index 9955a40f8fe56ddaaacc07d92925720635274c98..94448a001cdbae6977c8c325c34e755d353abac6 100644 >--- a/Source/WebKit/UIProcess/API/wpe/webkit.h >+++ b/Source/WebKit/UIProcess/API/wpe/webkit.h >@@ -69,6 +69,7 @@ > #include <wpe/WebKitURISchemeRequest.h> > #include <wpe/WebKitURIUtilities.h> > #include <wpe/WebKitUserContent.h> >+#include <wpe/WebKitUserContentFilterStore.h> > #include <wpe/WebKitUserContentManager.h> > #include <wpe/WebKitUserMediaPermissionRequest.h> > #include <wpe/WebKitVersion.h> >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index cd6b717d98e8c30234d78b37bfa9cde280afc00c..d6bdf28b8be36c5d5faa3d4c92ee43baca106d4a 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,42 @@ >+2019-02-19 Adrian Perez de Castro <aperez@igalia.com> >+ >+ [WPE][GTK] Enable support for CONTENT_EXTENSIONS >+ https://bugs.webkit.org/show_bug.cgi?id=167941 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * MiniBrowser/gtk/main.c: >+ (filterSavedCallback): Added. >+ (main): Support loading a JSON rule set file for content filtering. >+ * MiniBrowser/wpe/main.cpp: >+ (filterSavedCallback): Added. >+ (main): Support loading a JSON rule set file for content filtering. >+ * TestWebKitAPI/Tests/WebKitGLib/TestWebKitUserContentFilterStore.cpp: Added. >+ (WTF::refGPtr): Added locally for WebKitUserContentFilter, as it would not be used anywhere else. >+ (WTF::derefGPtr): Ditto. >+ (testEmptyStore): >+ (testSaveInvalidFilter): >+ (testSaveLoadFilter): >+ (testSavedFilterIdentifierMatch): >+ (testRemoveFilter): >+ (testSaveMultipleFilters): >+ (testSaveFilterFromFile): >+ (testFilterPersistence): >+ (beforeAll): >+ (afterAll): >+ * TestWebKitAPI/Tests/WebKitGLib/TestWebKitUserContentManager.cpp: >+ (removeOldInjectedContentAndResetLists): Also reset content filters. >+ (isCSSBlockedForURLAtPath): Added. Tests whether the test filter, which blocks a >+ CSS style sheet, has blocked the load of the CSS by looking at the resulting style of >+ the element affected by the style sheet. >+ (getUserContentFilter): Added. Stores the test filter in a WebKitUserContentFilterStore >+ and returns it to be used by tests. >+ (testUserContentManagerContentFilter): Added. Tests whether adding and removing a filter >+ from the WebKitUserContentManager results in the a CSS style sheet being blocked. >+ (serverCallback): Add support for serving a CSS style sheet for testing. >+ (beforeAll): Add call to testUserContentManagerContentFilter(). >+ * TestWebKitAPI/glib/CMakeLists.txt: Added TestWebKitUserContentFilterStore. >+ > 2019-02-19 Keith Rollin <krollin@apple.com> > > Add timing information to build output >diff --git a/Tools/MiniBrowser/gtk/main.c b/Tools/MiniBrowser/gtk/main.c >index afbe555ea5283bbb7c8743f4a3767f6e5cd1ee41..133284ff15a8e250a670ae53dbee82be9a844a59 100644 >--- a/Tools/MiniBrowser/gtk/main.c >+++ b/Tools/MiniBrowser/gtk/main.c >@@ -48,6 +48,7 @@ static gboolean privateMode; > static gboolean automationMode; > static gboolean fullScreen; > static gboolean ignoreTLSErrors; >+static const char *contentFilter; > static const char *cookiesFile; > static const char *cookiesPolicy; > static const char *proxy; >@@ -112,6 +113,7 @@ static const GOptionEntry commandLineOptions[] = > { "proxy", 0, 0, G_OPTION_ARG_STRING, &proxy, "Set proxy", "PROXY" }, > { "ignore-host", 0, 0, G_OPTION_ARG_STRING_ARRAY, &ignoreHosts, "Set proxy ignore hosts", "HOSTS" }, > { "ignore-tls-errors", 0, 0, G_OPTION_ARG_NONE, &ignoreTLSErrors, "Ignore TLS errors", NULL }, >+ { "content-filter", 0, 0, G_OPTION_ARG_FILENAME, &contentFilter, "JSON with content filtering rules", "FILE" }, > { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, 0, "[URLâ¦]" }, > { 0, 0, 0, 0, 0, 0, 0 } > }; >@@ -471,6 +473,18 @@ static void automationStartedCallback(WebKitWebContext *webContext, WebKitAutoma > g_signal_connect(session, "create-web-view", G_CALLBACK(createWebViewForAutomationCallback), NULL); > } > >+typedef struct { >+ GMainLoop *mainLoop; >+ WebKitUserContentFilter *filter; >+ GError *error; >+} FilterSaveData; >+ >+static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResult *result, FilterSaveData *data) >+{ >+ data->filter = webkit_user_content_filter_store_save_finish(store, result, &data->error); >+ g_main_loop_quit(data->mainLoop); >+} >+ > int main(int argc, char *argv[]) > { > #if ENABLE_DEVELOPER_MODE >@@ -539,6 +553,30 @@ int main(int argc, char *argv[]) > webkit_user_content_manager_register_script_message_handler(userContentManager, "aboutData"); > g_signal_connect(userContentManager, "script-message-received::aboutData", G_CALLBACK(aboutDataScriptMessageReceivedCallback), webContext); > >+ if (contentFilter) { >+ GFile *contentFilterFile = g_file_new_for_commandline_arg(contentFilter); >+ >+ FilterSaveData saveData = { NULL, NULL, NULL }; >+ gchar *filtersPath = g_build_filename(g_get_user_cache_dir(), g_get_prgname(), "filters", NULL); >+ WebKitUserContentFilterStore *store = webkit_user_content_filter_store_new(filtersPath); >+ g_free(filtersPath); >+ >+ webkit_user_content_filter_store_save_from_file(store, "GTKMiniBrowserFilter", contentFilterFile, NULL, (GAsyncReadyCallback)filterSavedCallback, &saveData); >+ saveData.mainLoop = g_main_loop_new(NULL, FALSE); >+ g_main_loop_run(saveData.mainLoop); >+ g_object_unref(store); >+ >+ if (saveData.filter) >+ webkit_user_content_manager_add_filter(userContentManager, saveData.filter); >+ else >+ g_printerr("Cannot save filter '%s': %s\n", contentFilter, saveData.error->message); >+ >+ g_clear_pointer(&saveData.error, g_error_free); >+ g_clear_pointer(&saveData.filter, webkit_user_content_filter_unref); >+ g_main_loop_unref(saveData.mainLoop); >+ g_object_unref(contentFilterFile); >+ } >+ > webkit_web_context_set_automation_allowed(webContext, automationMode); > g_signal_connect(webContext, "automation-started", G_CALLBACK(automationStartedCallback), NULL); > >diff --git a/Tools/MiniBrowser/wpe/main.cpp b/Tools/MiniBrowser/wpe/main.cpp >index 131a0f387090b347752408f9ea416dba180affaa..863c4c0e38a5362a19b39118c95e0c3c5aa1aba7 100644 >--- a/Tools/MiniBrowser/wpe/main.cpp >+++ b/Tools/MiniBrowser/wpe/main.cpp >@@ -39,6 +39,7 @@ static gboolean headlessMode; > static gboolean privateMode; > static gboolean automationMode; > static gboolean ignoreTLSErrors; >+static const char* contentFilter; > static const char* cookiesFile; > static const char* cookiesPolicy; > static const char* proxy; >@@ -53,6 +54,7 @@ static const GOptionEntry commandLineOptions[] = > { "proxy", 0, 0, G_OPTION_ARG_STRING, &proxy, "Set proxy", "PROXY" }, > { "ignore-host", 0, 0, G_OPTION_ARG_STRING_ARRAY, &ignoreHosts, "Set proxy ignore hosts", "HOSTS" }, > { "ignore-tls-errors", 0, 0, G_OPTION_ARG_NONE, &ignoreTLSErrors, "Ignore TLS errors", nullptr }, >+ { "content-filter", 0, 0, G_OPTION_ARG_FILENAME, &contentFilter, "JSON with content filtering rules", "FILE" }, > { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &uriArguments, nullptr, "[URL]" }, > { nullptr, 0, 0, G_OPTION_ARG_NONE, nullptr, nullptr, nullptr } > }; >@@ -125,6 +127,18 @@ static std::unique_ptr<WPEToolingBackends::ViewBackend> createViewBackend(uint32 > return std::make_unique<WPEToolingBackends::WindowViewBackend>(width, height); > } > >+typedef struct { >+ GMainLoop* mainLoop { nullptr }; >+ WebKitUserContentFilter* filter { nullptr }; >+ GError* error { nullptr }; >+} FilterSaveData; >+ >+static void filterSavedCallback(WebKitUserContentFilterStore *store, GAsyncResult *result, FilterSaveData *data) >+{ >+ data->filter = webkit_user_content_filter_store_save_finish(store, result, &data->error); >+ g_main_loop_quit(data->mainLoop); >+} >+ > int main(int argc, char *argv[]) > { > #if ENABLE_DEVELOPER_MODE >@@ -184,6 +198,32 @@ int main(int argc, char *argv[]) > webkit_web_context_set_process_model(webContext, (singleprocess && *singleprocess) ? > WEBKIT_PROCESS_MODEL_SHARED_SECONDARY_PROCESS : WEBKIT_PROCESS_MODEL_MULTIPLE_SECONDARY_PROCESSES); > >+ WebKitUserContentManager* userContentManager = nullptr; >+ if (contentFilter) { >+ GFile* contentFilterFile = g_file_new_for_commandline_arg(contentFilter); >+ >+ FilterSaveData saveData = { nullptr, }; >+ gchar* filtersPath = g_build_filename(g_get_user_cache_dir(), g_get_prgname(), "filters", nullptr); >+ WebKitUserContentFilterStore* store = webkit_user_content_filter_store_new(filtersPath); >+ g_free(filtersPath); >+ >+ webkit_user_content_filter_store_save_from_file(store, "WPEMiniBrowserFilter", contentFilterFile, nullptr, (GAsyncReadyCallback)filterSavedCallback, &saveData); >+ saveData.mainLoop = g_main_loop_new(nullptr, FALSE); >+ g_main_loop_run(saveData.mainLoop); >+ g_object_unref(store); >+ >+ if (saveData.filter) { >+ userContentManager = webkit_user_content_manager_new(); >+ webkit_user_content_manager_add_filter(userContentManager, saveData.filter); >+ } else >+ g_printerr("Cannot save filter '%s': %s\n", contentFilter, saveData.error->message); >+ >+ g_clear_pointer(&saveData.error, g_error_free); >+ g_clear_pointer(&saveData.filter, webkit_user_content_filter_unref); >+ g_main_loop_unref(saveData.mainLoop); >+ g_object_unref(contentFilterFile); >+ } >+ > auto* settings = webkit_settings_new_with_settings( > "enable-developer-extras", TRUE, > "enable-webgl", TRUE, >@@ -200,6 +240,7 @@ int main(int argc, char *argv[]) > "backend", viewBackend, > "web-context", webContext, > "settings", settings, >+ "user-content-manager", userContentManager, > "is-controlled-by-automation", automationMode, > nullptr)); > g_object_unref(settings); >diff --git a/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitUserContentFilterStore.cpp b/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitUserContentFilterStore.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..e3243d6cbde09013bdf51279157f965b9d286c5a >--- /dev/null >+++ b/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitUserContentFilterStore.cpp >@@ -0,0 +1,297 @@ >+/* >+ * Copyright (C) 2019 Igalia S.L. >+ * >+ * This library is free software; you can redistribute it and/or >+ * modify it under the terms of the GNU Lesser General Public >+ * License as published by the Free Software Foundation; either >+ * version 2,1 of the License, or (at your option) any later version. >+ * >+ * This library 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 >+ * Library General Public License for more details. >+ * >+ * You should have received a copy of the GNU Library General Public License >+ * along with this library; see the file COPYING.LIB. If not, write to >+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, >+ * Boston, MA 02110-1301, USA. >+ */ >+ >+#include "config.h" >+ >+#include "TestMain.h" >+#include <wtf/glib/GRefPtr.h> >+#include <wtf/glib/GUniquePtr.h> >+ >+static const char* kInvalidJSONSources[] = { >+ // Empty input. >+ "", >+ // Incorrect JSON input. >+ "[", >+ "]", >+ "[{]", >+ "[{ \"trigger: {} }]", >+ "[{ 'trigger': { 'url-filter': '.*' }, 'action': { 'type': 'block' } }]", >+ // Oddball JSON objects. >+ "{}", >+ "[]", >+ "[{}]", >+ // Empty trigger/action. >+ "[{ \"trigger\": {} }]", >+ "[{ \"action\": {} }]", >+ "[{ \"trigger\": {}, \"action\": {} }]", >+ "[{ \"trigger\": { \"url-filter\": \".*\" } }]", >+ "[{ \"trigger\": { \"url-filter\": \".*\" }, \"action\": {} }]", >+ // Empty action type. >+ "[{ \"trigger\": { \"url-filter\": \".*\" }, \"action\": { \"type\": \"\" } }]", >+ // Empty URL filter. >+ "[{ \"trigger\": { \"url-filter\": \"\" }, \"action\": { \"type\": \"block\" } }]", >+}; >+ >+static const char* kSimpleJSONSource = >+ "[{\n" >+ " \"trigger\": {\n" >+ " \"url-filter\": \".*\"\n" >+ " },\n" >+ " \"action\": {\n" >+ " \"type\": \"block\"\n" >+ " }\n" >+ "}]\n"; >+ >+namespace WTF { >+ >+template <> WebKitUserContentFilter* refGPtr(WebKitUserContentFilter* ptr) >+{ >+ if (ptr) >+ webkit_user_content_filter_ref(ptr); >+ return ptr; >+} >+ >+template <> void derefGPtr(WebKitUserContentFilter* ptr) >+{ >+ if (ptr) >+ webkit_user_content_filter_unref(ptr); >+} >+ >+} >+ >+class UserContentFilterStoreTest: public Test { >+public: >+ MAKE_GLIB_TEST_FIXTURE(UserContentFilterStoreTest); >+ >+ GError* lastError() const >+ { >+ return m_error.get(); >+ } >+ >+ void resetStore() >+ { >+ auto* oldStore = m_filterStore.get(); >+ m_filterStore = newStore(); >+ g_assert_true(oldStore != m_filterStore.get()); >+ } >+ >+ char** fetchIdentifiers() >+ { >+ webkit_user_content_filter_store_fetch_identifiers(m_filterStore.get(), nullptr, [](GObject* sourceObject, GAsyncResult* result, void* userData) { >+ auto* test = static_cast<UserContentFilterStoreTest*>(userData); >+ test->m_filterIds.reset(webkit_user_content_filter_store_fetch_identifiers_finish(WEBKIT_USER_CONTENT_FILTER_STORE(sourceObject), result)); >+ g_main_loop_quit(test->m_mainLoop.get()); >+ }, this); >+ g_main_loop_run(m_mainLoop.get()); >+ g_assert_nonnull(m_filterIds.get()); >+ return m_filterIds.get(); >+ } >+ >+ WebKitUserContentFilter* saveFilter(const char* filterId, const char* source) >+ { >+ GRefPtr<GBytes> sourceBytes = adoptGRef(g_bytes_new_static(source, strlen(source))); >+ webkit_user_content_filter_store_save(m_filterStore.get(), filterId, sourceBytes.get(), nullptr, [](GObject* sourceObject, GAsyncResult* result, void* userData) { >+ auto* test = static_cast<UserContentFilterStoreTest*>(userData); >+ test->m_filter = adoptGRef(webkit_user_content_filter_store_save_finish(WEBKIT_USER_CONTENT_FILTER_STORE(sourceObject), result, &test->m_error.outPtr())); >+ g_main_loop_quit(test->m_mainLoop.get()); >+ }, this); >+ g_main_loop_run(m_mainLoop.get()); >+ return m_filter.get(); >+ } >+ >+ WebKitUserContentFilter* saveFilterFromFile(const char* filterId, GFile* file) >+ { >+ webkit_user_content_filter_store_save_from_file(m_filterStore.get(), filterId, file, nullptr, [](GObject* sourceObject, GAsyncResult* result, void* userData) { >+ auto* test = static_cast<UserContentFilterStoreTest*>(userData); >+ test->m_filter = adoptGRef(webkit_user_content_filter_store_save_from_file_finish(WEBKIT_USER_CONTENT_FILTER_STORE(sourceObject), result, &test->m_error.outPtr())); >+ g_main_loop_quit(test->m_mainLoop.get()); >+ }, this); >+ g_main_loop_run(m_mainLoop.get()); >+ return m_filter.get(); >+ } >+ >+ WebKitUserContentFilter* loadFilter(const char* filterId) >+ { >+ webkit_user_content_filter_store_load(m_filterStore.get(), filterId, nullptr, [](GObject* sourceObject, GAsyncResult* result, void* userData) { >+ auto* test = static_cast<UserContentFilterStoreTest*>(userData); >+ test->m_filter = adoptGRef(webkit_user_content_filter_store_load_finish(WEBKIT_USER_CONTENT_FILTER_STORE(sourceObject), result, &test->m_error.outPtr())); >+ g_main_loop_quit(test->m_mainLoop.get()); >+ }, this); >+ g_main_loop_run(m_mainLoop.get()); >+ return m_filter.get(); >+ } >+ >+ bool removeFilter(const char* filterId) >+ { >+ webkit_user_content_filter_store_remove(m_filterStore.get(), filterId, nullptr, [](GObject* sourceObject, GAsyncResult* result, void* userData) { >+ auto* test = static_cast<UserContentFilterStoreTest*>(userData); >+ test->m_completedOk = !!webkit_user_content_filter_store_remove_finish(WEBKIT_USER_CONTENT_FILTER_STORE(sourceObject), result, &test->m_error.outPtr()); >+ g_main_loop_quit(test->m_mainLoop.get()); >+ }, this); >+ g_main_loop_run(m_mainLoop.get()); >+ return m_completedOk; >+ } >+ >+private: >+ GRefPtr<WebKitUserContentFilterStore> newStore() >+ { >+ GUniquePtr<char> storagePath(g_build_filename(dataDirectory(), "content-filters", nullptr)); >+ auto store = adoptGRef(webkit_user_content_filter_store_new(storagePath.get())); >+ g_assert_nonnull(store.get()); >+ assertObjectIsDeletedWhenTestFinishes(G_OBJECT(store.get())); >+ g_assert_cmpstr(storagePath.get(), ==, webkit_user_content_filter_store_get_path(store.get())); >+ return store; >+ } >+ >+ GRefPtr<WebKitUserContentFilterStore> m_filterStore { newStore() }; >+ GRefPtr<GMainLoop> m_mainLoop { adoptGRef(g_main_loop_new(nullptr, FALSE)) }; >+ GRefPtr<WebKitUserContentFilter> m_filter; >+ GUniquePtr<char*> m_filterIds; >+ GUniqueOutPtr<GError> m_error; >+ bool m_completedOk; >+}; >+ >+static void testEmptyStore(UserContentFilterStoreTest* test, gconstpointer) >+{ >+ g_assert_cmpuint(0, ==, g_strv_length(test->fetchIdentifiers())); >+} >+ >+static void testSaveInvalidFilter(UserContentFilterStoreTest* test, gconstpointer) >+{ >+ for (unsigned i = 0; i < G_N_ELEMENTS(kInvalidJSONSources); i++) { >+ GUniquePtr<char> filterId(g_strdup_printf("Filter-%u", i)); >+ g_assert_null(test->saveFilter(filterId.get(), kInvalidJSONSources[i])); >+ g_assert_error(test->lastError(), WEBKIT_USER_CONTENT_FILTER_ERROR, WEBKIT_USER_CONTENT_FILTER_ERROR_INVALID_SOURCE); >+ } >+} >+ >+static void testSaveLoadFilter(UserContentFilterStoreTest* test, gconstpointer) >+{ >+ static const char* kFilterId = "SimpleFilter"; >+ >+ // Trying to load a filter before saving must fail. >+ g_assert_null(test->loadFilter(kFilterId)); >+ g_assert_error(test->lastError(), WEBKIT_USER_CONTENT_FILTER_ERROR, WEBKIT_USER_CONTENT_FILTER_ERROR_NOT_FOUND); >+ >+ // Then save a filter. Which must succed. >+ g_assert_nonnull(test->saveFilter(kFilterId, kSimpleJSONSource)); >+ g_assert_no_error(test->lastError()); >+ >+ // Now it should be possible to actually load the filter. >+ g_assert_nonnull(test->loadFilter(kFilterId)); >+ g_assert_no_error(test->lastError()); >+} >+ >+static void testSavedFilterIdentifierMatch(UserContentFilterStoreTest* test, gconstpointer) >+{ >+ static const char* kFilterId = "SimpleFilter"; >+ >+ auto* filter = test->saveFilter(kFilterId, kSimpleJSONSource); >+ g_assert_nonnull(filter); >+ g_assert_no_error(test->lastError()); >+ g_assert_cmpstr(kFilterId, ==, webkit_user_content_filter_get_identifier(filter)); >+} >+ >+static void testRemoveFilter(UserContentFilterStoreTest* test, gconstpointer) >+{ >+ static const char* kFilterId = "SimpleFilter"; >+ >+ // Save a filter. >+ g_assert_nonnull(test->saveFilter(kFilterId, kSimpleJSONSource)); >+ g_assert_no_error(test->lastError()); >+ >+ // Now remove it. >+ g_assert_true(test->removeFilter(kFilterId)); >+ g_assert_no_error(test->lastError()); >+ >+ // Load must fail, and should not be listed. >+ g_assert_null(test->loadFilter(kFilterId)); >+ g_assert_error(test->lastError(), WEBKIT_USER_CONTENT_FILTER_ERROR, WEBKIT_USER_CONTENT_FILTER_ERROR_NOT_FOUND); >+ g_assert_cmpuint(0, ==, g_strv_length(test->fetchIdentifiers())); >+} >+ >+static void testSaveMultipleFilters(UserContentFilterStoreTest* test, gconstpointer) >+{ >+ static const char* kFilterIdSpam = "Filter-Spam"; >+ static const char* kFilterIdEggs = "Filter-Eggs"; >+ >+ g_assert_nonnull(test->saveFilter(kFilterIdSpam, kSimpleJSONSource)); >+ g_assert_no_error(test->lastError()); >+ >+ g_assert_nonnull(test->saveFilter(kFilterIdEggs, kSimpleJSONSource)); >+ g_assert_no_error(test->lastError()); >+ >+ auto filterIds = test->fetchIdentifiers(); >+ g_assert_true(g_strv_contains(filterIds, kFilterIdSpam)); >+ g_assert_true(g_strv_contains(filterIds, kFilterIdEggs)); >+ g_assert_cmpuint(2, ==, g_strv_length(filterIds)); >+ >+ g_assert_nonnull(test->saveFilter(kFilterIdEggs, kSimpleJSONSource)); >+ g_assert_no_error(test->lastError()); >+ >+ filterIds = test->fetchIdentifiers(); >+ g_assert_true(g_strv_contains(filterIds, kFilterIdSpam)); >+ g_assert_true(g_strv_contains(filterIds, kFilterIdEggs)); >+ g_assert_cmpuint(2, ==, g_strv_length(filterIds)); >+} >+ >+static void testSaveFilterFromFile(UserContentFilterStoreTest* test, gconstpointer) >+{ >+ static const char* kFilterId = "SimpleFilter"; >+ >+ GUniqueOutPtr<GError> error; >+ GUniquePtr<char> filePath(g_build_filename(test->dataDirectory(), "SimpleFilter.json", nullptr)); >+ g_assert_true(g_file_set_contents(filePath.get(), kSimpleJSONSource, strlen(kSimpleJSONSource), &error.outPtr())); >+ g_assert_no_error(error.get()); >+ >+ GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(filePath.get())); >+ g_assert_nonnull(test->saveFilterFromFile(kFilterId, file.get())); >+ g_assert_no_error(test->lastError()); >+ >+ g_assert_true(g_strv_contains(test->fetchIdentifiers(), kFilterId)); >+} >+ >+static void testFilterPersistence(UserContentFilterStoreTest* test, gconstpointer) >+{ >+ static const char* kFilterId = "PersistedFilter"; >+ >+ g_assert_nonnull(test->saveFilter(kFilterId, kSimpleJSONSource)); >+ g_assert_no_error(test->lastError()); >+ >+ test->resetStore(); >+ >+ g_assert_nonnull(test->loadFilter(kFilterId)); >+ g_assert_no_error(test->lastError()); >+} >+ >+void beforeAll() >+{ >+ UserContentFilterStoreTest::add("WebKitUserContentFilterStore", "empty-store", testEmptyStore); >+ UserContentFilterStoreTest::add("WebKitUserContentFilterStore", "invalid-filter-source", testSaveInvalidFilter); >+ UserContentFilterStoreTest::add("WebKitUserContentFilterStore", "filter-save-load", testSaveLoadFilter); >+ UserContentFilterStoreTest::add("WebKitUserContentFilterStore", "saved-filter-identifier-match", testSavedFilterIdentifierMatch); >+ UserContentFilterStoreTest::add("WebKitUserContentFilterStore", "remove-filter", testRemoveFilter); >+ UserContentFilterStoreTest::add("WebKitUserContentFilterStore", "save-multiple-filters", testSaveMultipleFilters); >+ UserContentFilterStoreTest::add("WebKitUserContentFilterStore", "save-from-file", testSaveFilterFromFile); >+ UserContentFilterStoreTest::add("WebKitUserContentFilterStore", "filter-persistence", testFilterPersistence); >+} >+ >+void afterAll() >+{ >+} >diff --git a/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitUserContentManager.cpp b/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitUserContentManager.cpp >index 20ecca850ffc4e3e10c84a3448d4ad3528b43823..01db4f139e78c4af2824fff3ae0410f2ab5d1fcb 100644 >--- a/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitUserContentManager.cpp >+++ b/Tools/TestWebKitAPI/Tests/WebKitGLib/TestWebKitUserContentManager.cpp >@@ -28,13 +28,40 @@ > static WebKitTestServer* kServer; > > // These are all here so that they can be changed easily, if necessary. >-static const char* kStyleSheetHTML = "<html><div id=\"styledElement\">Sweet stylez!</div></html>"; >+static const char* kTestHTML = >+"<html>\n" >+" <head><link rel=\"stylesheet\" type=\"text/css\" href=\"/extra.css\"></head>\n" >+" <body>\n" >+" <div id=\"styledElement\">Sweet stylez!</div>\n" >+" <div id=\"otherElement\">Blocked stylez!</div>\n" >+" </body>\n" >+"</html>"; >+ >+static const char* kTestCSS = >+"div#otherElement {\n" >+" font-weight: bold;\n" >+"}\n"; >+ > static const char* kInjectedStyleSheet = "#styledElement { font-weight: bold; }"; > static const char* kStyleSheetTestScript = "getComputedStyle(document.getElementById('styledElement'))['font-weight']"; > static const char* kStyleSheetTestScriptResult = "bold"; > static const char* kInjectedScript = "document.write('<div id=\"item\">Generated by a script</div>')"; > static const char* kScriptTestScript = "document.getElementById('item').innerText"; > static const char* kScriptTestScriptResult = "Generated by a script"; >+static const char* kScriptTestCSSBlocked = "getComputedStyle(document.getElementById('otherElement'))['font-weight']"; >+static const char* kScriptTestCSSBlockedResult = "normal"; >+static const char* kJSONFilter = >+"[\n" >+" {\n" >+" \"trigger\": {\n" >+" \"url-filter\": \".*\",\n" >+" \"resource-type\": [\"style-sheet\"]\n" >+" },\n" >+" \"action\": {\n" >+" \"type\": \"block\"\n" >+" }\n" >+" }\n" >+"]\n"; > > static void testWebViewNewWithUserContentManager(Test* test, gconstpointer) > { >@@ -97,6 +124,7 @@ static void removeOldInjectedContentAndResetLists(WebKitUserContentManager* user > { > webkit_user_content_manager_remove_all_style_sheets(userContentManager); > webkit_user_content_manager_remove_all_scripts(userContentManager); >+ webkit_user_content_manager_remove_all_filters(userContentManager); > > while (*whitelist) { > g_free(*whitelist); >@@ -404,10 +432,76 @@ static void testUserContentManagerScriptMessageFromDOMBindings(UserScriptMessage > } > #endif > >+static bool isCSSBlockedForURLAtPath(WebViewTest* test, const char* path) >+{ >+ test->loadURI(kServer->getURIForPath(path).data()); >+ test->waitUntilLoadFinished(); >+ >+ GUniqueOutPtr<GError> error; >+ WebKitJavascriptResult* javascriptResult = test->runJavaScriptAndWaitUntilFinished(kScriptTestCSSBlocked, &error.outPtr()); >+ g_assert_nonnull(javascriptResult); >+ g_assert_no_error(error.get()); >+ >+ GUniquePtr<char> valueString(WebViewTest::javascriptResultToCString(javascriptResult)); >+ return !g_strcmp0(valueString.get(), kScriptTestCSSBlockedResult); >+} >+ >+static WebKitUserContentFilter* getUserContentFilter(WebViewTest* test) >+{ >+ GUniquePtr<char> filtersPath(g_build_filename(test->dataDirectory(), "filters", nullptr)); >+ WebKitUserContentFilterStore* store = webkit_user_content_filter_store_new(filtersPath.get()); >+ test->assertObjectIsDeletedWhenTestFinishes(G_OBJECT(store)); >+ >+ struct Data { >+ GMainLoop* mainLoop; >+ WebKitUserContentFilter* filter; >+ }; >+ Data data { test->m_mainLoop, nullptr, }; >+ >+ GRefPtr<GBytes> source = adoptGRef(g_bytes_new_static(kJSONFilter, strlen(kJSONFilter))); >+ webkit_user_content_filter_store_save(store, "TestFilter", source.get(), nullptr, [](GObject* sourceObject, GAsyncResult* result, void* userData) { >+ auto* data = static_cast<Data*>(userData); >+ GUniqueOutPtr<GError> error; >+ data->filter = webkit_user_content_filter_store_save_finish(WEBKIT_USER_CONTENT_FILTER_STORE(sourceObject), result, &error.outPtr()); >+ g_assert_nonnull(data->filter); >+ g_assert_no_error(error.get()); >+ g_main_loop_quit(data->mainLoop); >+ }, &data); >+ g_main_loop_run(data.mainLoop); >+ >+ g_object_unref(store); >+ >+ g_assert_nonnull(data.filter); >+ return data.filter; >+} >+ >+static void testUserContentManagerContentFilter(WebViewTest* test, gconstpointer) >+{ >+ char* whitelist[] = { nullptr, nullptr, nullptr }; >+ char* blacklist[] = { nullptr, nullptr, nullptr }; >+ >+ removeOldInjectedContentAndResetLists(test->m_userContentManager.get(), whitelist, blacklist); >+ >+ static const char* somePath = "somepath"; >+ g_assert_false(isCSSBlockedForURLAtPath(test, somePath)); >+ >+ WebKitUserContentFilter* filter = getUserContentFilter(test); >+ webkit_user_content_manager_add_filter(test->m_userContentManager.get(), filter); >+ g_assert_true(isCSSBlockedForURLAtPath(test, somePath)); >+ >+ webkit_user_content_manager_remove_filter(test->m_userContentManager.get(), filter); >+ g_assert_false(isCSSBlockedForURLAtPath(test, somePath)); >+ >+ webkit_user_content_filter_unref(filter); >+} >+ > static void serverCallback(SoupServer* server, SoupMessage* message, const char* path, GHashTable*, SoupClientContext*, gpointer) > { > soup_message_set_status(message, SOUP_STATUS_OK); >- soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kStyleSheetHTML, strlen(kStyleSheetHTML)); >+ if (!g_strcmp0(path, "/extra.css")) >+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kTestCSS, strlen(kTestCSS)); >+ else >+ soup_message_body_append(message->response_body, SOUP_MEMORY_STATIC, kTestHTML, strlen(kTestHTML)); > soup_message_body_complete(message->response_body); > } > >@@ -424,6 +518,7 @@ void beforeAll() > #if PLATFORM(GTK) > UserScriptMessageTest::add("WebKitUserContentManager", "script-message-from-dom-bindings", testUserContentManagerScriptMessageFromDOMBindings); > #endif >+ WebViewTest::add("WebKitUserContentManager", "content-filter", testUserContentManagerContentFilter); > } > > void afterAll() >diff --git a/Tools/TestWebKitAPI/glib/CMakeLists.txt b/Tools/TestWebKitAPI/glib/CMakeLists.txt >index 056634c57705a8438ec7282964b5f273fbe30552..65a00780032ca6c8dd88583a6244c532026956d8 100644 >--- a/Tools/TestWebKitAPI/glib/CMakeLists.txt >+++ b/Tools/TestWebKitAPI/glib/CMakeLists.txt >@@ -141,6 +141,7 @@ ADD_WK2_TEST(TestWebKitSettings ${TOOLS_DIR}/TestWebKitAPI/Tests/WebKitGLib/Test > ADD_WK2_TEST(TestWebKitURIUtilities ${TOOLS_DIR}/TestWebKitAPI/Tests/WebKitGLib/TestWebKitURIUtilities.cpp) > ADD_WK2_TEST(TestWebKitWebContext ${TOOLS_DIR}/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebContext.cpp) > ADD_WK2_TEST(TestWebKitWebView ${TOOLS_DIR}/TestWebKitAPI/Tests/WebKitGLib/TestWebKitWebView.cpp) >+ADD_WK2_TEST(TestWebKitUserContentFilterStore ${TOOLS_DIR}/TestWebKitAPI/Tests/WebKitGLib/TestWebKitUserContentFilterStore.cpp) > ADD_WK2_TEST(TestWebKitUserContentManager ${TOOLS_DIR}/TestWebKitAPI/Tests/WebKitGLib/TestWebKitUserContentManager.cpp) > ADD_WK2_TEST(TestWebsiteData ${TOOLS_DIR}/TestWebKitAPI/Tests/WebKitGLib/TestWebsiteData.cpp) > ADD_WK2_TEST(TestConsoleMessage ${TOOLS_DIR}/TestWebKitAPI/Tests/WebKitGLib/TestConsoleMessage.cpp)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 167941
:
300813
|
300820
|
300823
|
300824
|
300826
|
300913
|
300918
|
301041
|
301050
|
301263
|
303066
|
303124
|
303125
|
357177
|
357215
|
359725
|
359895
|
359972
|
360918
|
361851
|
361875
|
361981
|
362081
|
362184
|
362334
|
362419
| 362488