LeOSium_webview/LeOS/patches/eyeo-beta-118.0.5993.48-and...

5303 lines
224 KiB
Diff
Raw Normal View History

2023-11-18 11:46:19 +01:00
From: chromium-sdk <project_26591639_bot@noreply.gitlab.com>
Date: Thu, 12 Oct 2023 14:46:06 +0200
Subject: eyeo Browser Ad filtering Solution: Android API Module
Based on Chromium 118.0.5993.48
Pre-requisites: eyeo Browser Ad filtering Solution: Base Module
---
chrome/android/BUILD.gn | 10 +
chrome/browser/BUILD.gn | 14 +
.../android/adblock/adblock_jni_factory.cc | 72 +++
.../android/adblock/adblock_jni_factory.h | 50 ++
...iltering_configuration_bindings_factory.cc | 70 +++
...filtering_configuration_bindings_factory.h | 51 ++
.../adblock/java_bindings_getters_impl.cc | 88 +++
...lassification_notifier_bindings_factory.cc | 71 +++
...classification_notifier_bindings_factory.h | 52 ++
...hrome_browser_main_extra_parts_profiles.cc | 10 +
components/adblock/android/BUILD.gn | 99 +++
components/adblock/android/adblock_jni.cc | 176 ++++++
components/adblock/android/adblock_jni.h | 52 ++
.../filtering_configuration_bindings.cc | 295 +++++++++
.../filtering_configuration_bindings.h | 68 +++
.../adblock/AdblockContentType.java | 61 ++
.../components/adblock/AdblockController.java | 203 +++++++
.../components/adblock/AdblockCounters.java | 101 ++++
.../adblock/FilteringConfiguration.java | 348 +++++++++++
.../ResourceClassificationNotifier.java | 187 ++++++
.../adblock/android/java_bindings_getters.h | 41 ++
.../adblock/AdblockControllerTestBase.java | 63 ++
.../adblock/TestAdBlockedObserver.java | 176 ++++++
.../TestPagesCircumventionTestBase.java | 64 ++
.../adblock/TestPagesCspTestBase.java | 108 ++++
.../TestPagesElemhideEmuInvTestBase.java | 135 +++++
.../adblock/TestPagesElemhideEmuTestBase.java | 183 ++++++
.../adblock/TestPagesElemhideTestBase.java | 204 +++++++
.../adblock/TestPagesExceptionTestBase.java | 174 ++++++
.../adblock/TestPagesFilterTestBase.java | 254 ++++++++
.../TestPagesHeaderFilterTestBase.java | 125 ++++
.../adblock/TestPagesHelperBase.java | 180 ++++++
.../adblock/TestPagesRewriteTestBase.java | 153 +++++
.../adblock/TestPagesSiteKeyTestBase.java | 58 ++
.../adblock/TestPagesSnippetsTestBase.java | 562 ++++++++++++++++++
.../adblock/TestPagesWebsocketTestBase.java | 56 ++
.../adblock/TestVerificationUtils.java | 163 +++++
...source_classification_notifier_bindings.cc | 164 +++++
...esource_classification_notifier_bindings.h | 69 +++
39 files changed, 5010 insertions(+)
create mode 100644 chrome/browser/android/adblock/adblock_jni_factory.cc
create mode 100644 chrome/browser/android/adblock/adblock_jni_factory.h
create mode 100644 chrome/browser/android/adblock/filtering_configuration_bindings_factory.cc
create mode 100644 chrome/browser/android/adblock/filtering_configuration_bindings_factory.h
create mode 100644 chrome/browser/android/adblock/java_bindings_getters_impl.cc
create mode 100644 chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.cc
create mode 100644 chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h
create mode 100644 components/adblock/android/BUILD.gn
create mode 100644 components/adblock/android/adblock_jni.cc
create mode 100644 components/adblock/android/adblock_jni.h
create mode 100644 components/adblock/android/filtering_configuration_bindings.cc
create mode 100644 components/adblock/android/filtering_configuration_bindings.h
create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java
create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java
create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java
create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java
create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java
create mode 100644 components/adblock/android/java_bindings_getters.h
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHelperBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTestBase.java
create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java
create mode 100644 components/adblock/android/resource_classification_notifier_bindings.cc
create mode 100644 components/adblock/android/resource_classification_notifier_bindings.h
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -3438,6 +3438,17 @@ static_library("browser") {
"webauthn/android/webauthn_request_delegate_android.h",
]
+ ### Android API module start
+ sources += [
+ "android/adblock/adblock_jni_factory.cc",
+ "android/adblock/adblock_jni_factory.h",
+ "android/adblock/filtering_configuration_bindings_factory.cc",
+ "android/adblock/filtering_configuration_bindings_factory.h",
+ "android/adblock/java_bindings_getters_impl.cc",
+ "android/adblock/resource_classification_notifier_bindings_factory.cc",
+ "android/adblock/resource_classification_notifier_bindings_factory.h",
+ ]
+ ### Android API module end
public_deps += [
"//chrome/android/features/dev_ui:buildflags",
@@ -3627,6 +3638,9 @@ static_library("browser") {
"//url:gurl_android",
]
+ ###Android API module start
+ deps += [ "//components/adblock/android:java_bindings" ]
+ ###Android API module end
if (safe_browsing_mode == 2) {
sources += [
diff --git a/chrome/browser/android/adblock/adblock_jni_factory.cc b/chrome/browser/android/adblock/adblock_jni_factory.cc
new file mode 100644
--- /dev/null
+++ b/chrome/browser/android/adblock/adblock_jni_factory.cc
@@ -0,0 +1,72 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "chrome/browser/android/adblock/adblock_jni_factory.h"
+
+#include <memory>
+
+#include "chrome/browser/adblock/subscription_service_factory.h"
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/adblock/android/adblock_jni.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "content/public/browser/browser_context.h"
+
+namespace adblock {
+
+// static
+AdblockJNI* AdblockJNIFactory::GetForBrowserContext(
+ content::BrowserContext* context) {
+ return static_cast<AdblockJNI*>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+// static
+AdblockJNIFactory* AdblockJNIFactory::GetInstance() {
+ static base::NoDestructor<AdblockJNIFactory> instance;
+ return instance.get();
+}
+
+AdblockJNIFactory::AdblockJNIFactory()
+ : BrowserContextKeyedServiceFactory(
+ "AdblockJNI",
+ BrowserContextDependencyManager::GetInstance()) {
+ DependsOn(SubscriptionServiceFactory::GetInstance());
+}
+
+AdblockJNIFactory::~AdblockJNIFactory() = default;
+
+KeyedService* AdblockJNIFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ return new AdblockJNI(
+ SubscriptionServiceFactory::GetForBrowserContext(context));
+}
+
+content::BrowserContext* AdblockJNIFactory::GetBrowserContextToUse(
+ content::BrowserContext* context) const {
+ return chrome::GetBrowserContextRedirectedInIncognito(context);
+}
+
+bool AdblockJNIFactory::ServiceIsCreatedWithBrowserContext() const {
+ // This avoids manual instantiation in chrome_browser_main.cc
+ return true;
+}
+
+bool AdblockJNIFactory::ServiceIsNULLWhileTesting() const {
+ return true;
+}
+
+} // namespace adblock
diff --git a/chrome/browser/android/adblock/adblock_jni_factory.h b/chrome/browser/android/adblock/adblock_jni_factory.h
new file mode 100644
--- /dev/null
+++ b/chrome/browser/android/adblock/adblock_jni_factory.h
@@ -0,0 +1,50 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_FACTORY_H_
+#define CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_FACTORY_H_
+
+#include "base/no_destructor.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "content/public/browser/browser_context.h"
+
+namespace adblock {
+
+class AdblockJNI;
+class AdblockJNIFactory : public BrowserContextKeyedServiceFactory {
+ public:
+ public:
+ static AdblockJNI* GetForBrowserContext(content::BrowserContext* context);
+ static AdblockJNIFactory* GetInstance();
+
+ private:
+ friend class base::NoDestructor<AdblockJNIFactory>;
+ AdblockJNIFactory();
+ ~AdblockJNIFactory() override;
+
+ // BrowserContextKeyedServiceFactory:
+ KeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const override;
+ content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const override;
+ bool ServiceIsCreatedWithBrowserContext() const override;
+ bool ServiceIsNULLWhileTesting() const override;
+};
+
+} // namespace adblock
+
+#endif // CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_FACTORY_H_
diff --git a/chrome/browser/android/adblock/filtering_configuration_bindings_factory.cc b/chrome/browser/android/adblock/filtering_configuration_bindings_factory.cc
new file mode 100644
--- /dev/null
+++ b/chrome/browser/android/adblock/filtering_configuration_bindings_factory.cc
@@ -0,0 +1,70 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "chrome/browser/android/adblock/filtering_configuration_bindings_factory.h"
+
+#include "chrome/browser/adblock/subscription_service_factory.h"
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/adblock/android/filtering_configuration_bindings.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+namespace adblock {
+
+// static
+FilteringConfigurationBindings*
+FilteringConfigurationBindingsFactory::GetForBrowserContext(
+ content::BrowserContext* context) {
+ return static_cast<FilteringConfigurationBindings*>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+// static
+FilteringConfigurationBindingsFactory*
+FilteringConfigurationBindingsFactory::GetInstance() {
+ static base::NoDestructor<FilteringConfigurationBindingsFactory> instance;
+ return instance.get();
+}
+
+FilteringConfigurationBindingsFactory::FilteringConfigurationBindingsFactory()
+ : BrowserContextKeyedServiceFactory(
+ "FilteringConfigurationBindings",
+ BrowserContextDependencyManager::GetInstance()) {
+ DependsOn(SubscriptionServiceFactory::GetInstance());
+}
+
+FilteringConfigurationBindingsFactory::
+ ~FilteringConfigurationBindingsFactory() = default;
+
+KeyedService* FilteringConfigurationBindingsFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ return new FilteringConfigurationBindings(
+ SubscriptionServiceFactory::GetForBrowserContext(context),
+ Profile::FromBrowserContext(context)->GetOriginalProfile()->GetPrefs());
+}
+
+content::BrowserContext*
+FilteringConfigurationBindingsFactory::GetBrowserContextToUse(
+ content::BrowserContext* context) const {
+ return chrome::GetBrowserContextRedirectedInIncognito(context);
+}
+
+bool FilteringConfigurationBindingsFactory::ServiceIsCreatedWithBrowserContext()
+ const {
+ return true;
+}
+
+} // namespace adblock
diff --git a/chrome/browser/android/adblock/filtering_configuration_bindings_factory.h b/chrome/browser/android/adblock/filtering_configuration_bindings_factory.h
new file mode 100644
--- /dev/null
+++ b/chrome/browser/android/adblock/filtering_configuration_bindings_factory.h
@@ -0,0 +1,51 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CHROME_BROWSER_ANDROID_ADBLOCK_FILTERING_CONFIGURATION_BINDINGS_FACTORY_H_
+#define CHROME_BROWSER_ANDROID_ADBLOCK_FILTERING_CONFIGURATION_BINDINGS_FACTORY_H_
+
+#include "base/no_destructor.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "content/public/browser/browser_context.h"
+
+namespace adblock {
+
+class FilteringConfigurationBindings;
+class FilteringConfigurationBindingsFactory
+ : public BrowserContextKeyedServiceFactory {
+ public:
+ public:
+ static FilteringConfigurationBindings* GetForBrowserContext(
+ content::BrowserContext* context);
+ static FilteringConfigurationBindingsFactory* GetInstance();
+
+ private:
+ friend class base::NoDestructor<FilteringConfigurationBindingsFactory>;
+ FilteringConfigurationBindingsFactory();
+ ~FilteringConfigurationBindingsFactory() override;
+
+ // BrowserContextKeyedServiceFactory:
+ KeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const override;
+ content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const override;
+ bool ServiceIsCreatedWithBrowserContext() const override;
+};
+
+} // namespace adblock
+
+#endif // CHROME_BROWSER_ANDROID_ADBLOCK_FILTERING_CONFIGURATION_BINDINGS_FACTORY_H_
diff --git a/chrome/browser/android/adblock/java_bindings_getters_impl.cc b/chrome/browser/android/adblock/java_bindings_getters_impl.cc
new file mode 100644
--- /dev/null
+++ b/chrome/browser/android/adblock/java_bindings_getters_impl.cc
@@ -0,0 +1,88 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "components/adblock/android/java_bindings_getters.h"
+
+#include "chrome/browser/adblock/subscription_service_factory.h"
+#include "chrome/browser/android/adblock/adblock_jni_factory.h"
+#include "chrome/browser/android/adblock/filtering_configuration_bindings_factory.h"
+#include "chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h"
+#include "chrome/browser/android/tab_android.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "components/adblock/android/filtering_configuration_bindings.h"
+#include "components/adblock/android/resource_classification_notifier_bindings.h"
+#include "content/public/browser/web_contents.h"
+
+namespace adblock {
+namespace {
+constexpr int kNoTabId = -1;
+}
+
+SubscriptionService* GetSubscriptionService() {
+ if (!g_browser_process || !g_browser_process->profile_manager()) {
+ return nullptr;
+ }
+ return SubscriptionServiceFactory::GetForBrowserContext(
+ g_browser_process->profile_manager()->GetLastUsedProfile());
+}
+
+AdblockJNI* GetJNI() {
+ if (!g_browser_process || !g_browser_process->profile_manager()) {
+ return nullptr;
+ }
+ return AdblockJNIFactory::GetForBrowserContext(
+ g_browser_process->profile_manager()->GetLastUsedProfile());
+}
+
+adblock::FilteringConfigurationBindings& GetFilteringConfigurationBindings() {
+ auto* bindings =
+ adblock::FilteringConfigurationBindingsFactory::GetForBrowserContext(
+ g_browser_process->profile_manager()->GetLastUsedProfile());
+ DCHECK(bindings) << "FilteringConfigurationBindings should be non-null even "
+ "in tests, to keep the code simple";
+ return *bindings;
+}
+
+adblock::ResourceClassificationNotifierBindings&
+GetResourceClassificationNotifierBindings() {
+ auto* bindings = adblock::ResourceClassificationNotifierBindingsFactory::
+ GetForBrowserContext(
+ g_browser_process->profile_manager()->GetLastUsedProfile());
+ DCHECK(bindings)
+ << "ResourceClassificationNotifierBindings should be non-null even "
+ "in tests, to keep the code simple";
+ return *bindings;
+}
+
+int GetTabId(content::RenderFrameHost* render_frame_host) {
+ auto* web_contents =
+ content::WebContents::FromRenderFrameHost(render_frame_host);
+ if (!web_contents) {
+ return kNoTabId;
+ }
+
+ auto* tab = TabAndroid::FromWebContents(web_contents);
+ if (!tab) {
+ return kNoTabId;
+ }
+
+ return tab->GetAndroidId();
+}
+
+} // namespace adblock
diff --git a/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.cc b/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.cc
new file mode 100644
--- /dev/null
+++ b/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.cc
@@ -0,0 +1,71 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h"
+
+#include "chrome/browser/adblock/resource_classification_runner_factory.h"
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "components/adblock/android/resource_classification_notifier_bindings.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+namespace adblock {
+
+// static
+ResourceClassificationNotifierBindings*
+ResourceClassificationNotifierBindingsFactory::GetForBrowserContext(
+ content::BrowserContext* context) {
+ return static_cast<ResourceClassificationNotifierBindings*>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+// static
+ResourceClassificationNotifierBindingsFactory*
+ResourceClassificationNotifierBindingsFactory::GetInstance() {
+ static base::NoDestructor<ResourceClassificationNotifierBindingsFactory>
+ instance;
+ return instance.get();
+}
+
+ResourceClassificationNotifierBindingsFactory::
+ ResourceClassificationNotifierBindingsFactory()
+ : BrowserContextKeyedServiceFactory(
+ "ResourceClassificationNotifierBindings",
+ BrowserContextDependencyManager::GetInstance()) {
+ DependsOn(ResourceClassificationRunnerFactory::GetInstance());
+}
+
+ResourceClassificationNotifierBindingsFactory::
+ ~ResourceClassificationNotifierBindingsFactory() = default;
+
+KeyedService*
+ResourceClassificationNotifierBindingsFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ return new ResourceClassificationNotifierBindings(
+ ResourceClassificationRunnerFactory::GetForBrowserContext(context));
+}
+
+content::BrowserContext*
+ResourceClassificationNotifierBindingsFactory::GetBrowserContextToUse(
+ content::BrowserContext* context) const {
+ return chrome::GetBrowserContextRedirectedInIncognito(context);
+}
+
+bool ResourceClassificationNotifierBindingsFactory::
+ ServiceIsCreatedWithBrowserContext() const {
+ return true;
+}
+
+} // namespace adblock
diff --git a/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h b/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h
new file mode 100644
--- /dev/null
+++ b/chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef CHROME_BROWSER_ANDROID_ADBLOCK_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_FACTORY_H_
+#define CHROME_BROWSER_ANDROID_ADBLOCK_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_FACTORY_H_
+
+#include "base/no_destructor.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "content/public/browser/browser_context.h"
+
+namespace adblock {
+
+class ResourceClassificationNotifierBindings;
+class ResourceClassificationNotifierBindingsFactory
+ : public BrowserContextKeyedServiceFactory {
+ public:
+ public:
+ static ResourceClassificationNotifierBindings* GetForBrowserContext(
+ content::BrowserContext* context);
+ static ResourceClassificationNotifierBindingsFactory* GetInstance();
+
+ private:
+ friend class base::NoDestructor<
+ ResourceClassificationNotifierBindingsFactory>;
+ ResourceClassificationNotifierBindingsFactory();
+ ~ResourceClassificationNotifierBindingsFactory() override;
+
+ // BrowserContextKeyedServiceFactory:
+ KeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* context) const override;
+ content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const override;
+ bool ServiceIsCreatedWithBrowserContext() const override;
+};
+
+} // namespace adblock
+
+#endif // CHROME_BROWSER_ANDROID_ADBLOCK_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_FACTORY_H_
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -263,6 +263,11 @@
#include "components/commerce/core/commerce_feature_list.h"
#include "components/commerce/core/proto/merchant_signal_db_content.pb.h"
+// Android API module start
+#include "chrome/browser/android/adblock/adblock_jni_factory.h"
+#include "chrome/browser/android/adblock/filtering_configuration_bindings_factory.h"
+#include "chrome/browser/android/adblock/resource_classification_notifier_bindings_factory.h"
+// Android API module end
#else
#include "chrome/browser/accessibility/live_caption/live_caption_controller_factory.h"
@@ -762,6 +767,11 @@ void ChromeBrowserMainExtraPartsProfiles::
#if BUILDFLAG(IS_ANDROID)
FastCheckoutCapabilitiesFetcherFactory::GetInstance();
+ // Android API module start
+ adblock::AdblockJNIFactory::GetInstance();
+ adblock::FilteringConfigurationBindingsFactory::GetInstance();
+ adblock::ResourceClassificationNotifierBindingsFactory::GetInstance();
+ // Android API module end
#endif
FaviconServiceFactory::GetInstance();
diff --git a/components/adblock/android/BUILD.gn b/components/adblock/android/BUILD.gn
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/BUILD.gn
@@ -0,0 +1,99 @@
+# This file is part of eyeo Chromium SDK,
+# Copyright (C) 2006-present eyeo GmbH
+# eyeo Chromium SDK is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 3 as
+# published by the Free Software Foundation.
+# eyeo Chromium SDK is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+# You should have received a copy of the GNU General Public License
+# along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+
+
+import("//build/config/android/rules.gni")
+import("//build/config/locales.gni")
+import("//tools/grit/grit_rule.gni")
+
+source_set("java_bindings") {
+ sources = [
+ "adblock_jni.cc",
+ "adblock_jni.h",
+ "filtering_configuration_bindings.cc",
+ "filtering_configuration_bindings.h",
+ "java_bindings_getters.h",
+ "resource_classification_notifier_bindings.cc",
+ "resource_classification_notifier_bindings.h",
+ ]
+ deps = [
+ ":jni_headers",
+ "//base",
+ "//components/keyed_service/content:content",
+ ]
+
+ public_deps = [
+ "//components/adblock/content:browser",
+ "//components/adblock/core/configuration",
+ "//components/adblock/core/subscription",
+ "//components/prefs",
+ ]
+}
+
+generate_jni("jni_headers") {
+ sources = [
+ "java/src/org/chromium/components/adblock/AdblockController.java",
+ "java/src/org/chromium/components/adblock/FilteringConfiguration.java",
+ "java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java",
+ ]
+}
+
+android_library("adblock_controller_java") {
+ sources = [
+ "java/src/org/chromium/components/adblock/AdblockContentType.java",
+ "java/src/org/chromium/components/adblock/AdblockController.java",
+ "java/src/org/chromium/components/adblock/AdblockCounters.java",
+ "java/src/org/chromium/components/adblock/FilteringConfiguration.java",
+ "java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java",
+ ]
+
+ srcjar_deps = [ ":jni_headers" ]
+ deps = [
+ "//base:base_java",
+ "//base:jni_java",
+ "//third_party/androidx:androidx_annotation_annotation_java",
+ ]
+
+ resources_package = "org.chromium.components.adblock.controller"
+}
+
+
+android_library("adblock_java_tests_base") {
+ testonly = true
+ sources = [
+ "javatests/src/org/chromium/components/adblock/AdblockControllerTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesCircumventionTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesCspTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesElemhideTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesExceptionTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesFilterTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesHelperBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesRewriteTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesSnippetsTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestPagesWebsocketTestBase.java",
+ "javatests/src/org/chromium/components/adblock/TestVerificationUtils.java",
+ ]
+ deps = [
+ ":adblock_controller_java",
+ "//base:base_java",
+ "//base:base_java_test_support",
+ "//content/public/android:content_full_java",
+ "//content/public/test/android:content_java_test_support",
+ "//third_party/androidx:androidx_test_runner_java",
+ "//third_party/junit:junit",
+ ]
+}
diff --git a/components/adblock/android/adblock_jni.cc b/components/adblock/android/adblock_jni.cc
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/adblock_jni.cc
@@ -0,0 +1,176 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "components/adblock/android/adblock_jni.h"
+
+#include <algorithm>
+#include <iterator>
+#include <vector>
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/jni_weak_ref.h"
+#include "base/logging.h"
+#include "components/adblock/android/java_bindings_getters.h"
+#include "components/adblock/android/jni_headers/AdblockController_jni.h"
+#include "components/adblock/core/subscription/subscription_config.h"
+#include "content/public/browser/browser_thread.h"
+
+using base::android::AttachCurrentThread;
+using base::android::CheckException;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::GetClass;
+using base::android::JavaParamRef;
+using base::android::JavaRef;
+using base::android::MethodID;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+using base::android::ToJavaArrayOfObjects;
+using base::android::ToJavaArrayOfStrings;
+
+namespace adblock {
+
+namespace {
+
+ScopedJavaLocalRef<jobject> ToJava(JNIEnv* env,
+ ScopedJavaLocalRef<jclass>& url_class,
+ jmethodID& url_constructor,
+ const std::string& url,
+ const std::string& title,
+ const std::string& version,
+ const std::vector<std::string>& languages) {
+ ScopedJavaLocalRef<jobject> url_param(
+ env, env->NewObject(url_class.obj(), url_constructor,
+ ConvertUTF8ToJavaString(env, url).obj()));
+ CheckException(env);
+ return Java_Subscription_Constructor(env, url_param,
+ ConvertUTF8ToJavaString(env, title),
+ ConvertUTF8ToJavaString(env, version),
+ ToJavaArrayOfStrings(env, languages));
+}
+
+std::vector<ScopedJavaLocalRef<jobject>> CSubscriptionsToJObjects(
+ JNIEnv* env,
+ const std::vector<scoped_refptr<Subscription>>& subscriptions) {
+ ScopedJavaLocalRef<jclass> url_class = GetClass(env, "java/net/URL");
+ jmethodID url_constructor = MethodID::Get<MethodID::TYPE_INSTANCE>(
+ env, url_class.obj(), "<init>", "(Ljava/lang/String;)V");
+ std::vector<ScopedJavaLocalRef<jobject>> jobjects;
+ jobjects.reserve(subscriptions.size());
+ for (auto& sub : subscriptions) {
+ jobjects.push_back(ToJava(
+ env, url_class, url_constructor, sub->GetSourceUrl().spec(),
+ sub->GetTitle(), sub->GetCurrentVersion(), std::vector<std::string>{}));
+ }
+ return jobjects;
+}
+
+std::vector<ScopedJavaLocalRef<jobject>> CSubscriptionsToJObjects(
+ JNIEnv* env,
+ std::vector<KnownSubscriptionInfo>& subscriptions) {
+ ScopedJavaLocalRef<jclass> url_class = GetClass(env, "java/net/URL");
+ jmethodID url_constructor = MethodID::Get<MethodID::TYPE_INSTANCE>(
+ env, url_class.obj(), "<init>", "(Ljava/lang/String;)V");
+ std::vector<ScopedJavaLocalRef<jobject>> jobjects;
+ jobjects.reserve(subscriptions.size());
+ for (auto& sub : subscriptions) {
+ if (sub.ui_visibility == SubscriptionUiVisibility::Visible) {
+ // The checks here are when one makes f.e. adblock:custom visible
+ DCHECK(sub.url.is_valid());
+ if (sub.url.is_valid()) {
+ jobjects.push_back(ToJava(env, url_class, url_constructor,
+ sub.url.spec(), sub.title, "",
+ sub.languages));
+ }
+ }
+ }
+ return jobjects;
+}
+
+} // namespace
+
+AdblockJNI::AdblockJNI(SubscriptionService* subscription_service)
+ : subscription_service_(subscription_service) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (subscription_service_) {
+ subscription_service_->AddObserver(this);
+ }
+}
+
+AdblockJNI::~AdblockJNI() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (subscription_service_) {
+ subscription_service_->RemoveObserver(this);
+ }
+}
+
+void AdblockJNI::Bind(JavaObjectWeakGlobalRef weak_java_controller) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ weak_java_controller_ = weak_java_controller;
+}
+
+void AdblockJNI::OnSubscriptionInstalled(const GURL& url) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = weak_java_controller_.get(env);
+ if (obj.is_null()) {
+ return;
+ }
+
+ ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
+ Java_AdblockController_subscriptionUpdatedCallback(env, obj, j_url);
+}
+
+} // namespace adblock
+
+static void JNI_AdblockController_Bind(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& caller) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ if (!adblock::GetSubscriptionService()) {
+ return;
+ }
+ JavaObjectWeakGlobalRef weak_controller_ref(env, caller);
+ adblock::GetJNI()->Bind(weak_controller_ref);
+}
+
+static base::android::ScopedJavaLocalRef<jobjectArray>
+JNI_AdblockController_GetInstalledSubscriptions(JNIEnv* env) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ auto* subscription_service = adblock::GetSubscriptionService();
+ if (!subscription_service) {
+ return ToJavaArrayOfObjects(env,
+ std::vector<ScopedJavaLocalRef<jobject>>{});
+ }
+
+ return ToJavaArrayOfObjects(
+ env,
+ adblock::CSubscriptionsToJObjects(
+ env, subscription_service->GetCurrentSubscriptions(
+ subscription_service->GetAdblockFilteringConfiguration())));
+}
+
+static base::android::ScopedJavaLocalRef<jobjectArray>
+JNI_AdblockController_GetRecommendedSubscriptions(JNIEnv* env) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ auto list = adblock::config::GetKnownSubscriptions();
+ return ToJavaArrayOfObjects(env,
+ adblock::CSubscriptionsToJObjects(env, list));
+}
diff --git a/components/adblock/android/adblock_jni.h b/components/adblock/android/adblock_jni.h
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/adblock_jni.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef COMPONENTS_ADBLOCK_ANDROID_ADBLOCK_JNI_H_
+#define COMPONENTS_ADBLOCK_ANDROID_ADBLOCK_JNI_H_
+
+#include <string>
+
+#include "base/android/jni_weak_ref.h"
+#include "base/memory/raw_ptr.h"
+#include "components/adblock/core/subscription/subscription_service.h"
+#include "components/keyed_service/core/keyed_service.h"
+
+namespace content {
+class BrowserContext;
+}
+
+namespace adblock {
+
+class AdblockJNI : public SubscriptionService::SubscriptionObserver,
+ public KeyedService {
+ public:
+ explicit AdblockJNI(SubscriptionService* subscription_service);
+ ~AdblockJNI() override;
+
+ void Bind(JavaObjectWeakGlobalRef weak_java_controller);
+ // SubscriptionService::SubscriptionObserver
+ void OnSubscriptionInstalled(const GURL& subscription_url) override;
+
+ private:
+ SEQUENCE_CHECKER(sequence_checker_);
+ raw_ptr<SubscriptionService> subscription_service_;
+ JavaObjectWeakGlobalRef weak_java_controller_;
+};
+
+} // namespace adblock
+
+#endif // COMPONENTS_ADBLOCK_ANDROID_ADBLOCK_JNI_H_
diff --git a/components/adblock/android/filtering_configuration_bindings.cc b/components/adblock/android/filtering_configuration_bindings.cc
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/filtering_configuration_bindings.cc
@@ -0,0 +1,295 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "components/adblock/android/filtering_configuration_bindings.h"
+
+#include <iterator>
+#include <memory>
+
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/ranges/algorithm.h"
+#include "components/adblock/android/java_bindings_getters.h"
+#include "components/adblock/android/jni_headers/FilteringConfiguration_jni.h"
+#include "components/adblock/core/configuration/filtering_configuration.h"
+#include "components/adblock/core/configuration/persistent_filtering_configuration.h"
+#include "components/adblock/core/subscription/subscription_service.h"
+
+namespace adblock {
+
+FilteringConfigurationBindings::FilteringConfigurationBindings(
+ SubscriptionService* subscription_service,
+ PrefService* pref_service)
+ : subscription_service_(subscription_service),
+ pref_service_(pref_service) {}
+
+FilteringConfigurationBindings::~FilteringConfigurationBindings() {
+ for (auto& pair : bound_counterparts_) {
+ pair.first->RemoveObserver(this);
+ }
+}
+
+void FilteringConfigurationBindings::Bind(
+ const std::string& configuration_name,
+ JavaObjectWeakGlobalRef filtering_configuration_java) {
+ auto* existing_configuration =
+ GetInstalledConfigurationWithName(configuration_name);
+ if (existing_configuration) {
+ auto existing_binding = bound_counterparts_.find(existing_configuration);
+ if (existing_binding == bound_counterparts_.end()) {
+ // There is no Java-side counterpart bound to this
+ // FilteringConfiguration.
+ existing_configuration->AddObserver(this);
+ }
+ bound_counterparts_[existing_configuration] =
+ std::move(filtering_configuration_java);
+ } else {
+ // There is no already-installed FilteringConfiguration with this name.
+ // Create one and bind to it.
+ auto new_filtering_configuration =
+ std::make_unique<PersistentFilteringConfiguration>(pref_service_,
+ configuration_name);
+ new_filtering_configuration->AddObserver(this);
+ bound_counterparts_[new_filtering_configuration.get()] =
+ std::move(filtering_configuration_java);
+ subscription_service_->InstallFilteringConfiguration(
+ std::move(new_filtering_configuration));
+ }
+}
+
+void FilteringConfigurationBindings::RemoveConfiguration(
+ const std::string& configuration_name) {
+ auto* existing_configuration =
+ GetInstalledConfigurationWithName(configuration_name);
+ if (existing_configuration) {
+ existing_configuration->RemoveObserver(this);
+ bound_counterparts_.erase(existing_configuration);
+ subscription_service_->UninstallFilteringConfiguration(configuration_name);
+ }
+}
+
+std::vector<FilteringConfiguration*>
+FilteringConfigurationBindings::GetConfigurations() {
+ return subscription_service_->GetInstalledFilteringConfigurations();
+}
+
+FilteringConfiguration*
+FilteringConfigurationBindings::GetInstalledConfigurationWithName(
+ const std::string& configuration_name) {
+ const auto installed_configurations = GetConfigurations();
+ auto existing_configuration_it =
+ base::ranges::find(installed_configurations, configuration_name,
+ &FilteringConfiguration::GetName);
+ return existing_configuration_it != installed_configurations.end()
+ ? *existing_configuration_it
+ : nullptr;
+}
+
+void FilteringConfigurationBindings::OnEnabledStateChanged(
+ FilteringConfiguration* config) {
+ Notify(config, Java_FilteringConfiguration_enabledStateChanged);
+}
+
+void FilteringConfigurationBindings::OnFilterListsChanged(
+ FilteringConfiguration* config) {
+ Notify(config, Java_FilteringConfiguration_filterListsChanged);
+}
+
+void FilteringConfigurationBindings::OnAllowedDomainsChanged(
+ FilteringConfiguration* config) {
+ Notify(config, Java_FilteringConfiguration_allowedDomainsChanged);
+}
+
+void FilteringConfigurationBindings::OnCustomFiltersChanged(
+ FilteringConfiguration* config) {
+ Notify(config, Java_FilteringConfiguration_customFiltersChanged);
+}
+
+void FilteringConfigurationBindings::Notify(
+ FilteringConfiguration* config,
+ FilteringConfigurationBindings::JavaEventListener event_listener_function) {
+ auto bound_weak_ref = bound_counterparts_.find(config);
+ DCHECK(bound_weak_ref != bound_counterparts_.end())
+ << "This should never receive notifications from unobserved "
+ "FilteringConfigurations";
+ JNIEnv* env = base::android::AttachCurrentThread();
+ auto java_counterpart = bound_weak_ref->second.get(env);
+ if (!java_counterpart.is_null()) {
+ event_listener_function(env, java_counterpart);
+ }
+}
+
+} // namespace adblock
+
+// Throws when called with a name of a non existing configuration.
+adblock::FilteringConfiguration* GetConfigurationWithName(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name) {
+ auto& bindings = adblock::GetFilteringConfigurationBindings();
+ auto* configuration = bindings.GetInstalledConfigurationWithName(
+ base::android::ConvertJavaStringToUTF8(configuration_name));
+ if (!configuration) {
+ env->ThrowNew(env->FindClass("java/lang/IllegalStateException"),
+ "Configuration does not exist!");
+ return nullptr;
+ }
+ return configuration;
+}
+
+static void JNI_FilteringConfiguration_Bind(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name,
+ const base::android::JavaParamRef<jobject>& caller) {
+ auto& bindings = adblock::GetFilteringConfigurationBindings();
+ JavaObjectWeakGlobalRef weak_configuration_ref(env, caller);
+ auto cpp_name = base::android::ConvertJavaStringToUTF8(configuration_name);
+ bindings.Bind(cpp_name, weak_configuration_ref);
+}
+
+static void JNI_FilteringConfiguration_RemoveConfiguration(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name) {
+ auto& bindings = adblock::GetFilteringConfigurationBindings();
+ bindings.RemoveConfiguration(
+ base::android::ConvertJavaStringToUTF8(configuration_name));
+}
+
+static base::android::ScopedJavaLocalRef<jobjectArray>
+JNI_FilteringConfiguration_GetConfigurations(JNIEnv* env) {
+ auto& bindings = adblock::GetFilteringConfigurationBindings();
+ std::vector<std::string> configurations;
+ base::ranges::transform(
+ bindings.GetConfigurations(), std::back_inserter(configurations),
+ [](adblock::FilteringConfiguration* fc) { return fc->GetName(); });
+ return base::android::ToJavaArrayOfStrings(env, configurations);
+}
+
+static jboolean JNI_FilteringConfiguration_IsEnabled(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name) {
+ auto* configuration = GetConfigurationWithName(env, configuration_name);
+ return (configuration && configuration->IsEnabled()) ? JNI_TRUE : JNI_FALSE;
+}
+
+static void JNI_FilteringConfiguration_SetEnabled(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name,
+ jboolean j_enabled) {
+ auto* configuration = GetConfigurationWithName(env, configuration_name);
+ if (configuration) {
+ configuration->SetEnabled(j_enabled == JNI_TRUE);
+ }
+}
+
+static void JNI_FilteringConfiguration_AddFilterList(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name,
+ const base::android::JavaParamRef<jstring>& url) {
+ auto* configuration = GetConfigurationWithName(env, configuration_name);
+ if (configuration) {
+ configuration->AddFilterList(
+ GURL{base::android::ConvertJavaStringToUTF8(url)});
+ }
+}
+
+static void JNI_FilteringConfiguration_RemoveFilterList(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name,
+ const base::android::JavaParamRef<jstring>& url) {
+ auto* configuration = GetConfigurationWithName(env, configuration_name);
+ if (configuration) {
+ configuration->RemoveFilterList(
+ GURL{base::android::ConvertJavaStringToUTF8(url)});
+ }
+}
+
+static base::android::ScopedJavaLocalRef<jobjectArray>
+JNI_FilteringConfiguration_GetFilterLists(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name) {
+ // For simplicity, convert GURL to std::string, pass to Java, and convert from
+ // String to URL. Strings are easier to pass through JNI.
+ std::vector<std::string> urls;
+ auto* configuration = GetConfigurationWithName(env, configuration_name);
+ if (configuration) {
+ base::ranges::transform(configuration->GetFilterLists(),
+ std::back_inserter(urls), &GURL::spec);
+ }
+ return base::android::ToJavaArrayOfStrings(env, urls);
+}
+
+static void JNI_FilteringConfiguration_AddAllowedDomain(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name,
+ const base::android::JavaParamRef<jstring>& allowed_domain) {
+ auto* configuration = GetConfigurationWithName(env, configuration_name);
+ if (configuration) {
+ configuration->AddAllowedDomain(
+ base::android::ConvertJavaStringToUTF8(allowed_domain));
+ }
+}
+
+static void JNI_FilteringConfiguration_RemoveAllowedDomain(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name,
+ const base::android::JavaParamRef<jstring>& allowed_domain) {
+ auto* configuration = GetConfigurationWithName(env, configuration_name);
+ if (configuration) {
+ configuration->RemoveAllowedDomain(ConvertJavaStringToUTF8(allowed_domain));
+ }
+}
+
+static base::android::ScopedJavaLocalRef<jobjectArray>
+JNI_FilteringConfiguration_GetAllowedDomains(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name) {
+ auto* configuration = GetConfigurationWithName(env, configuration_name);
+ return base::android::ToJavaArrayOfStrings(
+ env, configuration ? configuration->GetAllowedDomains()
+ : std::vector<std::string>{});
+}
+
+static void JNI_FilteringConfiguration_AddCustomFilter(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name,
+ const base::android::JavaParamRef<jstring>& custom_filter) {
+ auto* configuration = GetConfigurationWithName(env, configuration_name);
+ if (configuration) {
+ configuration->AddCustomFilter(ConvertJavaStringToUTF8(custom_filter));
+ }
+}
+
+static void JNI_FilteringConfiguration_RemoveCustomFilter(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name,
+ const base::android::JavaParamRef<jstring>& custom_filter) {
+ auto* configuration = GetConfigurationWithName(env, configuration_name);
+ if (configuration) {
+ configuration->RemoveCustomFilter(
+ base::android::ConvertJavaStringToUTF8(custom_filter));
+ }
+}
+
+static base::android::ScopedJavaLocalRef<jobjectArray>
+JNI_FilteringConfiguration_GetCustomFilters(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jstring>& configuration_name) {
+ auto* configuration = GetConfigurationWithName(env, configuration_name);
+ return base::android::ToJavaArrayOfStrings(
+ env, configuration ? configuration->GetCustomFilters()
+ : std::vector<std::string>{});
+}
diff --git a/components/adblock/android/filtering_configuration_bindings.h b/components/adblock/android/filtering_configuration_bindings.h
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/filtering_configuration_bindings.h
@@ -0,0 +1,68 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef COMPONENTS_ADBLOCK_ANDROID_FILTERING_CONFIGURATION_BINDINGS_H_
+#define COMPONENTS_ADBLOCK_ANDROID_FILTERING_CONFIGURATION_BINDINGS_H_
+
+#include <map>
+#include <utility>
+#include <vector>
+#include "base/android/jni_weak_ref.h"
+#include "base/memory/raw_ptr.h"
+#include "base/sequence_checker.h"
+#include "components/adblock/core/configuration/filtering_configuration.h"
+#include "components/adblock/core/subscription/subscription_service.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "components/prefs/pref_service.h"
+
+namespace adblock {
+
+class FilteringConfigurationBindings : public KeyedService,
+ public FilteringConfiguration::Observer {
+ public:
+ explicit FilteringConfigurationBindings(
+ SubscriptionService* subscription_service,
+ PrefService* pref_service);
+ ~FilteringConfigurationBindings() override;
+ void Bind(const std::string& configuration_name,
+ JavaObjectWeakGlobalRef filtering_configuration_java);
+ void RemoveConfiguration(const std::string& configuration_name);
+ std::vector<FilteringConfiguration*> GetConfigurations();
+ FilteringConfiguration* GetInstalledConfigurationWithName(
+ const std::string& name);
+
+ // FilteringConfiguration::Observer:
+ void OnEnabledStateChanged(FilteringConfiguration* config) override;
+ void OnFilterListsChanged(FilteringConfiguration* config) override;
+ void OnAllowedDomainsChanged(FilteringConfiguration* config) override;
+ void OnCustomFiltersChanged(FilteringConfiguration* config) override;
+
+ private:
+ using JavaEventListener = void(JNIEnv* env,
+ const base::android::JavaRef<jobject>& obj);
+ void Notify(FilteringConfiguration* config,
+ JavaEventListener event_listener_function);
+ SEQUENCE_CHECKER(sequence_checker_);
+ raw_ptr<SubscriptionService> subscription_service_;
+ raw_ptr<PrefService> pref_service_;
+ std::map<FilteringConfiguration*, JavaObjectWeakGlobalRef>
+ bound_counterparts_;
+};
+
+} // namespace adblock
+
+#endif // COMPONENTS_ADBLOCK_ANDROID_FILTERING_CONFIGURATION_BINDINGS_H_
diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockContentType.java
@@ -0,0 +1,61 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public enum AdblockContentType {
+ // Note. This has to be kept in sync with c++ enum so some values
+ // are skipped
+ CONTENT_TYPE_OTHER(1 << 0),
+ CONTENT_TYPE_SCRIPT(1 << 1),
+ CONTENT_TYPE_IMAGE(1 << 2),
+ CONTENT_TYPE_STYLESHEET(1 << 3),
+ CONTENT_TYPE_OBJECT(1 << 4),
+ CONTENT_TYPE_SUBDOCUMENT(1 << 5),
+ CONTENT_TYPE_WEBSOCKET(1 << 7),
+ CONTENT_TYPE_WEBRTC(1 << 8),
+ CONTENT_TYPE_PING(1 << 10),
+ CONTENT_TYPE_XMLHTTPREQUEST(1 << 11),
+ CONTENT_TYPE_MEDIA(1 << 14),
+ CONTENT_TYPE_FONT(1 << 15);
+
+ private final int contentType;
+
+ private AdblockContentType(int contentType) {
+ this.contentType = contentType;
+ }
+
+ private static final Map<Integer, AdblockContentType> intToContentTypeMap =
+ new HashMap<Integer, AdblockContentType>();
+
+ static {
+ for (AdblockContentType type : AdblockContentType.values()) {
+ intToContentTypeMap.put(type.contentType, type);
+ }
+ }
+
+ public static AdblockContentType fromInt(int i) {
+ return intToContentTypeMap.get(i);
+ }
+
+ public int getValue() {
+ return contentType;
+ }
+}
diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockController.java
@@ -0,0 +1,203 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import android.content.Context;
+import android.util.Log;
+import android.webkit.URLUtil;
+
+import androidx.annotation.UiThread;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.NativeMethods;
+import org.chromium.components.adblock.controller.R;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @brief Main access point for java UI code to control ad filtering.
+ * It calls its native counter part also AdblockController.
+ * It lives in UI thread on the browser process.
+ */
+public final class AdblockController extends FilteringConfiguration {
+ private static final String TAG = AdblockController.class.getSimpleName();
+
+ private static AdblockController sInstance;
+
+ private URL mAcceptableAds;
+
+ private AdblockController() {
+ super("adblock");
+ try {
+ mAcceptableAds =
+ new URL("https://easylist-downloads.adblockplus.org/exceptionrules.txt");
+ } catch (java.net.MalformedURLException e) {
+ mAcceptableAds = null;
+ }
+ }
+
+ /**
+ * @return The singleton object.
+ */
+ public static AdblockController getInstance() {
+ ThreadUtils.assertOnUiThread();
+ if (sInstance == null) {
+ sInstance = new AdblockController();
+ AdblockControllerJni.get().bind(sInstance);
+ }
+ return sInstance;
+ }
+
+ public static class Subscription {
+ private URL mUrl;
+ private String mTitle;
+ private String mVersion = "";
+ private String[] mLanguages = {};
+
+ public Subscription(final URL url, final String title, final String version) {
+ this.mUrl = url;
+ this.mTitle = title;
+ this.mVersion = version;
+ }
+
+ @CalledByNative("Subscription")
+ public Subscription(
+ final URL url, final String title, final String version, final String[] languages) {
+ this.mUrl = url;
+ this.mTitle = title;
+ this.mVersion = version;
+ this.mLanguages = languages;
+ }
+
+ public String title() {
+ return mTitle;
+ }
+
+ public URL url() {
+ return mUrl;
+ }
+
+ public String version() {
+ return mVersion;
+ }
+
+ public String[] languages() {
+ return mLanguages;
+ }
+
+ @Override
+ public boolean equals(final Object object) {
+ if (object == null) return false;
+ if (getClass() != object.getClass()) return false;
+
+ Subscription other = (Subscription) object;
+ return url().equals(other.url());
+ }
+ }
+
+ @UiThread
+ public void setAcceptableAdsEnabled(boolean enabled) {
+ if (enabled)
+ addFilterList(mAcceptableAds);
+ else
+ removeFilterList(mAcceptableAds);
+ }
+
+ @UiThread
+ public boolean isAcceptableAdsEnabled() {
+ return getFilterLists().contains(mAcceptableAds);
+ }
+
+ @UiThread
+ public List<Subscription> getRecommendedSubscriptions() {
+ return (List<Subscription>) (List<?>) Arrays.asList(
+ AdblockControllerJni.get().getRecommendedSubscriptions());
+ }
+
+ @UiThread
+ public void installSubscription(final URL url) {
+ addFilterList(url);
+ }
+
+ @UiThread
+ public void uninstallSubscription(final URL url) {
+ removeFilterList(url);
+ }
+
+ @UiThread
+ public List<Subscription> getInstalledSubscriptions() {
+ return (List<Subscription>) (List<?>) Arrays.asList(
+ AdblockControllerJni.get().getInstalledSubscriptions());
+ }
+
+ // TODO(mpawlowski) temporary pass-through, to enable gradual deprecation.
+ public interface AdBlockedObserver extends ResourceClassificationNotifier.AdBlockedObserver {}
+ // TODO(mpawlowski) deprecate and remove, use ResourceClassificationNotifier directly.
+ @UiThread
+ public void addOnAdBlockedObserver(
+ final ResourceClassificationNotifier.AdBlockedObserver observer) {
+ ResourceClassificationNotifier.getInstance().addOnAdBlockedObserver(observer);
+ }
+
+ // TODO(mpawlowski) deprecate and remove, use ResourceClassifier directly.
+ @UiThread
+ public void removeOnAdBlockedObserver(
+ final ResourceClassificationNotifier.AdBlockedObserver observer) {
+ ResourceClassificationNotifier.getInstance().removeOnAdBlockedObserver(observer);
+ }
+
+ private List<URL> transform(String[] urls) {
+ if (urls == null) return null;
+
+ List<URL> result = new ArrayList<URL>();
+ for (String url : urls) {
+ try {
+ result.add(new URL(URLUtil.guessUrl(url)));
+ } catch (MalformedURLException e) {
+ Log.e(TAG, "Error parsing url: " + url);
+ }
+ }
+
+ return result;
+ }
+
+ @CalledByNative
+ private void subscriptionUpdatedCallback(final String url) {
+ ThreadUtils.assertOnUiThread();
+ try {
+ URL subscriptionUrl = new URL(URLUtil.guessUrl(url));
+ for (final SubscriptionUpdateObserver observer : mSubscriptionUpdateObservers) {
+ observer.onSubscriptionDownloaded(subscriptionUrl);
+ }
+ } catch (MalformedURLException e) {
+ Log.e(TAG, "Error parsing subscription url: " + url);
+ }
+ }
+
+ @NativeMethods
+ interface Natives {
+ void bind(AdblockController caller);
+ Object[] getInstalledSubscriptions();
+ Object[] getRecommendedSubscriptions();
+ }
+}
diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/java/src/org/chromium/components/adblock/AdblockCounters.java
@@ -0,0 +1,101 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class AdblockCounters {
+ /**
+ * Immutable data-class containing an auxiliary information about resource event.
+ */
+ public static class ResourceInfo {
+ private final String mRequestUrl;
+ private final List<String> mParentFrameUrls;
+ private final String mSubscriptionUrl;
+ private final String mConfigurationName;
+ private final AdblockContentType mAdblockContentType;
+ private final int mTabId;
+
+ ResourceInfo(final String requestUrl, final List<String> parentFrameUrls,
+ final String subscriptionUrl, final String configurationName,
+ final int adblockContentType, final int tabId) {
+ this.mRequestUrl = requestUrl;
+ this.mParentFrameUrls = parentFrameUrls;
+ this.mSubscriptionUrl = subscriptionUrl;
+ this.mConfigurationName = configurationName;
+ this.mAdblockContentType = AdblockContentType.fromInt(adblockContentType);
+ this.mTabId = tabId;
+ }
+
+ /**
+ * @return The request which was blocked or allowed.
+ */
+ public String getRequestUrl() {
+ return mRequestUrl;
+ }
+
+ /**
+ * @return The parent frames of the mRequestUrl.
+ */
+ public List<String> getParentFrameUrls() {
+ return mParentFrameUrls;
+ }
+
+ /**
+ * @return Subscription url for filter done blocking or allowing decision,
+ * empty string otherwise.
+ */
+ public String getSubscription() {
+ return mSubscriptionUrl;
+ }
+
+ /**
+ * @return Configuration name containing subscription with matched filer for
+ * blocking or allowing decision, empty string otherwise.
+ */
+ public String getConfigurationName() {
+ return mConfigurationName;
+ }
+
+ /**
+ * @return The Adblock content type. See enum ContentType in
+ * components/adblock/types.h
+ */
+ public AdblockContentType getAdblockContentType() {
+ return mAdblockContentType;
+ }
+
+ /**
+ * @return The current tab id for the mRequestUrl. -1 means no tab id, likely tab closed
+ * before event arrived. Numbers start from 0.
+ */
+ public int getTabId() {
+ return mTabId;
+ }
+
+ @Override
+ public String toString() {
+ return "mRequestUrl: " + mRequestUrl + ", mParentFrameUrls: "
+ + mParentFrameUrls.toString() + ", mSubscriptionUrl:" + mSubscriptionUrl
+ + ", mConfigurationName:" + mConfigurationName + ", mAdblockContentType: "
+ + mAdblockContentType.getValue() + ", mTabId: " + mTabId;
+ }
+ }
+}
diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java b/components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/java/src/org/chromium/components/adblock/FilteringConfiguration.java
@@ -0,0 +1,348 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+import android.webkit.URLUtil;
+
+import androidx.annotation.UiThread;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.NativeMethods;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @brief Represents an independent configuration of filters, filter lists,
+ * allowed domains and other settings that influence resource filtering and
+ * content blocking.
+ * Multiple Filtering Configurations can co-exist and be controlled separately.
+ * A network resource is blocked if any enabled Filtering Configuration
+ * determines it should be, through its filters.
+ * Elements on websites are hidden according to a superset of element-hiding
+ * selectors from all enabled Filtering Configurations.
+ * Lives on UI thread, not thread-safe.
+ */
+public class FilteringConfiguration {
+ private static final String TAG = FilteringConfiguration.class.getSimpleName();
+
+ private final Set<ConfigurationChangeObserver> mConfigurationChangeObservers = new HashSet<>();
+ protected final Set<SubscriptionUpdateObserver> mSubscriptionUpdateObservers = new HashSet<>();
+ private final String mName;
+ private final static Set<FilteringConfiguration> mConfigurations = new HashSet<>();
+
+ public interface ConfigurationChangeObserver {
+ /**
+ * Triggered when the FilteringConfiguration becomes disabled or enabled.
+ */
+ @UiThread
+ void onEnabledStateChanged();
+
+ /**
+ * Triggered when the collection of installed filter lists changes.
+ */
+ @UiThread
+ void onFilterListsChanged();
+
+ /**
+ * Triggered when the set of allowed domain changes.
+ */
+ @UiThread
+ void onAllowedDomainsChanged();
+
+ /**
+ * Triggered when the set of custom filters changes.
+ */
+ @UiThread
+ void onCustomFiltersChanged();
+ }
+
+ public interface SubscriptionUpdateObserver {
+ @UiThread
+ void onSubscriptionDownloaded(final URL url);
+ }
+
+ @UiThread
+ public void addObserver(final ConfigurationChangeObserver observer) {
+ mConfigurationChangeObservers.add(observer);
+ }
+
+ @UiThread
+ public void removeObserver(final ConfigurationChangeObserver observer) {
+ mConfigurationChangeObservers.remove(observer);
+ }
+
+ @UiThread
+ public void addSubscriptionUpdateObserver(final SubscriptionUpdateObserver observer) {
+ mSubscriptionUpdateObservers.add(observer);
+ }
+
+ @UiThread
+ public void removeSubscriptionUpdateObserver(final SubscriptionUpdateObserver observer) {
+ mSubscriptionUpdateObservers.remove(observer);
+ }
+
+ /**
+ * @throws IllegalStateException when called on removed FilteringConfiguration.
+ */
+ @UiThread
+ public void setEnabled(boolean enabled) throws IllegalStateException {
+ FilteringConfigurationJni.get().setEnabled(mName, enabled);
+ }
+
+ /**
+ * @throws IllegalStateException when called on removed FilteringConfiguration.
+ */
+ @UiThread
+ public boolean isEnabled() throws IllegalStateException {
+ return FilteringConfigurationJni.get().isEnabled(mName);
+ }
+
+ /**
+ * @throws IllegalStateException when called on removed FilteringConfiguration.
+ */
+ @UiThread
+ public void addFilterList(final URL url) throws IllegalStateException {
+ FilteringConfigurationJni.get().addFilterList(mName, url.toString());
+ }
+
+ /**
+ * @throws IllegalStateException when called on removed FilteringConfiguration.
+ */
+ @UiThread
+ public void removeFilterList(final URL url) throws IllegalStateException {
+ FilteringConfigurationJni.get().removeFilterList(mName, url.toString());
+ }
+
+ /**
+ * @throws IllegalStateException when called on removed FilteringConfiguration.
+ */
+ @UiThread
+ public List<URL> getFilterLists() throws IllegalStateException {
+ List<String> filterListsStr =
+ Arrays.asList(FilteringConfigurationJni.get().getFilterLists(mName));
+ List<URL> filterLists = new ArrayList<URL>();
+ for (String url : filterListsStr) {
+ try {
+ filterLists.add(new URL(url));
+ } catch (MalformedURLException e) {
+ Log.e(TAG, "Received invalid subscription URL from C++: " + url);
+ }
+ }
+ return filterLists;
+ }
+
+ /**
+ * @throws IllegalStateException when called on removed FilteringConfiguration.
+ */
+ @UiThread
+ public void addAllowedDomain(final String domain) throws IllegalStateException {
+ String sanitizedDomain = sanitizeSite(domain);
+ if (sanitizedDomain == null) return;
+ FilteringConfigurationJni.get().addAllowedDomain(mName, sanitizedDomain);
+ }
+
+ /**
+ * @throws IllegalStateException when called on removed FilteringConfiguration.
+ */
+
+ @UiThread
+ public void removeAllowedDomain(final String domain) throws IllegalStateException {
+ String sanitizedDomain = sanitizeSite(domain);
+ if (sanitizedDomain == null) return;
+ FilteringConfigurationJni.get().removeAllowedDomain(mName, sanitizedDomain);
+ }
+
+ /**
+ * @throws IllegalStateException when called on removed FilteringConfiguration.
+ */
+ @UiThread
+ public List<String> getAllowedDomains() throws IllegalStateException {
+ List<String> allowedDomains =
+ Arrays.asList(FilteringConfigurationJni.get().getAllowedDomains(mName));
+ Collections.sort(allowedDomains);
+ return allowedDomains;
+ }
+
+ /**
+ * @throws IllegalStateException when called on removed FilteringConfiguration.
+ */
+ @UiThread
+ public void addCustomFilter(final String filter) throws IllegalStateException {
+ FilteringConfigurationJni.get().addCustomFilter(mName, filter);
+ }
+
+ /**
+ * @throws IllegalStateException when called on removed FilteringConfiguration.
+ */
+ @UiThread
+ public void removeCustomFilter(final String filter) throws IllegalStateException {
+ FilteringConfigurationJni.get().removeCustomFilter(mName, filter);
+ }
+
+ /**
+ * @throws IllegalStateException when called on removed FilteringConfiguration.
+ */
+ @UiThread
+ public List<String> getCustomFilters() throws IllegalStateException {
+ return Arrays.asList(FilteringConfigurationJni.get().getCustomFilters(mName));
+ }
+
+ @UiThread
+ public static FilteringConfiguration createConfiguration(final String configuration_name) {
+ FilteringConfiguration configuration = findConfigurationByName(configuration_name);
+ if (configuration == null) {
+ configuration = new FilteringConfiguration(configuration_name);
+ mConfigurations.add(configuration);
+ }
+ return configuration;
+ }
+
+ @UiThread
+ public static void removeConfiguration(final String configuration_name) {
+ final FilteringConfiguration configuration = findConfigurationByName(configuration_name);
+ if (configuration != null) {
+ mConfigurations.remove(configuration);
+ }
+ // Even if on Java side there is no such a FilteringConfiguration object, it can exist
+ // on native side.
+ FilteringConfigurationJni.get().removeConfiguration(configuration_name);
+ }
+
+ @UiThread
+ public static List<FilteringConfiguration> getConfigurations() {
+ // Get all existing (on C++ side) configurations, if there is no matching Java
+ // instance present in mConfigurations set then create one and add.
+ final String[] existing_configurations_names =
+ FilteringConfigurationJni.get().getConfigurations();
+ final List<FilteringConfiguration> configurations_to_return =
+ new ArrayList<FilteringConfiguration>();
+ // If mConfigurations contains configurations which are not present on the list returned
+ // from FilteringConfigurationJni.get().getConfigurations() then we need to remove them
+ // as it means that a configuration has been removed on native side (not via Java API).
+ mConfigurations.removeIf(filteringConfiguration -> {
+ return !Arrays.asList(existing_configurations_names)
+ .contains(filteringConfiguration.mName);
+ });
+ for (final String configuration_name : existing_configurations_names) {
+ FilteringConfiguration configuration = findConfigurationByName(configuration_name);
+ if (configuration == null) {
+ configuration = new FilteringConfiguration(configuration_name);
+ mConfigurations.add(configuration);
+ }
+ configurations_to_return.add(configuration);
+ }
+ Collections.sort(configurations_to_return, new Comparator<FilteringConfiguration>() {
+ @Override
+ public int compare(
+ final FilteringConfiguration object1, final FilteringConfiguration object2) {
+ return object1.mName.compareTo(object2.mName);
+ }
+ });
+ return configurations_to_return;
+ }
+
+ // TODO(kzlomek): Make it private once we remove AdblockController (DPD-2120).
+ protected FilteringConfiguration(final String configuration_name) {
+ mName = configuration_name;
+ FilteringConfigurationJni.get().bind(mName, this);
+ }
+
+ @UiThread
+ private static FilteringConfiguration findConfigurationByName(final String configuration_name) {
+ for (final FilteringConfiguration configuration : mConfigurations) {
+ if (configuration.mName.equals(configuration_name)) {
+ return configuration;
+ }
+ }
+ return null;
+ }
+
+ private String sanitizeSite(String site) {
+ // |site| is raw user input. We expect it to be either a domain or a URL.
+ try {
+ URL candidate = new URL(URLUtil.guessUrl(site));
+ return candidate.getHost();
+ } catch (java.net.MalformedURLException e) {
+ }
+ // Could not parse |site| as URL or domain.
+ return null;
+ }
+
+ @CalledByNative
+ private void enabledStateChanged() {
+ ThreadUtils.assertOnUiThread();
+ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) {
+ observer.onEnabledStateChanged();
+ }
+ }
+
+ @CalledByNative
+ private void filterListsChanged() {
+ ThreadUtils.assertOnUiThread();
+ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) {
+ observer.onFilterListsChanged();
+ }
+ }
+
+ @CalledByNative
+ private void allowedDomainsChanged() {
+ ThreadUtils.assertOnUiThread();
+ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) {
+ observer.onAllowedDomainsChanged();
+ }
+ }
+
+ @CalledByNative
+ private void customFiltersChanged() {
+ ThreadUtils.assertOnUiThread();
+ for (final ConfigurationChangeObserver observer : mConfigurationChangeObservers) {
+ observer.onCustomFiltersChanged();
+ }
+ }
+
+ @NativeMethods
+ interface Natives {
+ void bind(String configuration_name, FilteringConfiguration caller);
+ void removeConfiguration(String configuration_name);
+ String[] getConfigurations();
+ boolean isEnabled(String configuration_name);
+ void setEnabled(String configuration_name, boolean enabled);
+ void addFilterList(String configuration_name, String url);
+ void removeFilterList(String configuration_name, String url);
+ String[] getFilterLists(String configuration_name);
+ void addAllowedDomain(String configuration_name, String domain);
+ void removeAllowedDomain(String configuration_name, String domain);
+ String[] getAllowedDomains(String configuration_name);
+ void addCustomFilter(String configuration_name, String filter);
+ void removeCustomFilter(String configuration_name, String filter);
+ String[] getCustomFilters(String configuration_name);
+ }
+}
diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java b/components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/java/src/org/chromium/components/adblock/ResourceClassificationNotifier.java
@@ -0,0 +1,187 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+import android.webkit.URLUtil;
+
+import androidx.annotation.UiThread;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.NativeMethods;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @brief Allows observing notifications from ongoing resource classification.
+ * Classification combines filters from all FilteringConfigurations.
+ * Lives on UI thread, not thread-safe.
+ */
+public final class ResourceClassificationNotifier {
+ private static final String TAG = ResourceClassificationNotifier.class.getSimpleName();
+
+ private static ResourceClassificationNotifier sInstance;
+ private final Set<AdBlockedObserver> mOnAdBlockedObservers = new HashSet<>();
+ // TODO(mpawlowski) in the future, we can consider adding filter hit
+ // notifications here as well (DPD-1233)
+
+ public interface AdBlockedObserver {
+ /**
+ * "Ad allowed" event for a request which would be blocked but there
+ * was an allowlisting filter found.
+ *
+ * It should not block the UI thread for too long.
+ * @param info contains auxiliary information about the resource.
+ */
+ @UiThread
+ void onAdAllowed(AdblockCounters.ResourceInfo info);
+
+ /**
+ * "Ad blocked" event for a request which was blocked.
+ *
+ * It should not block the UI thread for too long.
+ * @param info contains auxiliary information about the resource.
+ */
+ @UiThread
+ void onAdBlocked(AdblockCounters.ResourceInfo info);
+
+ /**
+ * "Page allowed" event for an allowlisted domain (page).
+ *
+ * It should not block the UI thread for too long.
+ * @param info contains auxiliary information about the resource.
+ */
+ @UiThread
+ void onPageAllowed(AdblockCounters.ResourceInfo info);
+
+ /**
+ * "Popup allowed" event for a popup which would be blocked but there
+ * was an allowlisting filter found.
+ *
+ * It should not block the UI thread for too long.
+ * @param info contains auxiliary information about the resource.
+ */
+ @UiThread
+ void onPopupAllowed(AdblockCounters.ResourceInfo info);
+
+ /**
+ * "Popup blocked" event for a popup which was blocked.
+ *
+ * It should not block the UI thread for too long.
+ * @param info contains auxiliary information about the resource.
+ */
+ @UiThread
+ void onPopupBlocked(AdblockCounters.ResourceInfo info);
+ }
+
+ private ResourceClassificationNotifier() {
+ ResourceClassificationNotifierJni.get().bind(this);
+ }
+
+ public static ResourceClassificationNotifier getInstance() {
+ ThreadUtils.assertOnUiThread();
+ if (sInstance == null) {
+ sInstance = new ResourceClassificationNotifier();
+ }
+ return sInstance;
+ }
+
+ @UiThread
+ public void addOnAdBlockedObserver(final AdBlockedObserver observer) {
+ mOnAdBlockedObservers.add(observer);
+ }
+
+ @UiThread
+ public void removeOnAdBlockedObserver(final AdBlockedObserver observer) {
+ mOnAdBlockedObservers.remove(observer);
+ }
+
+ @CalledByNative
+ private void adMatchedCallback(final String requestUrl, boolean wasBlocked,
+ final String[] parentFrameUrls, final String subscriptionUrl,
+ final String configurationName, final int contentType, final int tabId) {
+ ThreadUtils.assertOnUiThread();
+ final List<String> parentsList = Arrays.asList(parentFrameUrls);
+ final AdblockCounters.ResourceInfo resourceInfo = new AdblockCounters.ResourceInfo(
+ requestUrl, parentsList, subscriptionUrl, configurationName, contentType, tabId);
+ Log.d(TAG,
+ "eyeo: adMatchedCallback() notifies " + mOnAdBlockedObservers.size()
+ + " listeners about " + resourceInfo.toString()
+ + (wasBlocked ? " getting blocked" : " being allowed"));
+ for (final AdBlockedObserver observer : mOnAdBlockedObservers) {
+ if (wasBlocked) {
+ observer.onAdBlocked(resourceInfo);
+ } else {
+ observer.onAdAllowed(resourceInfo);
+ }
+ }
+ }
+
+ @CalledByNative
+ private void pageAllowedCallback(final String requestUrl, final String subscriptionUrl,
+ final String configurationName, final int tabId) {
+ ThreadUtils.assertOnUiThread();
+ final AdblockCounters.ResourceInfo resourceInfo =
+ new AdblockCounters.ResourceInfo(requestUrl, new ArrayList(), subscriptionUrl,
+ configurationName, AdblockContentType.CONTENT_TYPE_OTHER.getValue(), tabId);
+ Log.d(TAG,
+ "eyeo: pageAllowedCallback() notifies " + mOnAdBlockedObservers.size()
+ + " listeners about " + resourceInfo.toString());
+ for (final AdBlockedObserver observer : mOnAdBlockedObservers) {
+ observer.onPageAllowed(resourceInfo);
+ }
+ }
+
+ @CalledByNative
+ private void popupMatchedCallback(final String requestUrl, boolean wasBlocked,
+ final String openerUrl, final String subscription, final String configurationName,
+ final int tabId) {
+ ThreadUtils.assertOnUiThread();
+ final List<String> parentsList = Arrays.asList(openerUrl);
+ final AdblockCounters.ResourceInfo resourceInfo =
+ new AdblockCounters.ResourceInfo(requestUrl, parentsList, subscription,
+ configurationName, AdblockContentType.CONTENT_TYPE_OTHER.getValue(), tabId);
+ Log.d(TAG,
+ "eyeo: popupMatchedCallback() notifies " + mOnAdBlockedObservers.size()
+ + " listeners about " + resourceInfo.toString()
+ + (wasBlocked ? " getting blocked" : " being allowed"));
+ for (final AdBlockedObserver observer : mOnAdBlockedObservers) {
+ if (wasBlocked) {
+ observer.onPopupBlocked(resourceInfo);
+ } else {
+ observer.onPopupAllowed(resourceInfo);
+ }
+ }
+ }
+
+ @NativeMethods
+ interface Natives {
+ void bind(ResourceClassificationNotifier caller);
+ }
+}
diff --git a/components/adblock/android/java_bindings_getters.h b/components/adblock/android/java_bindings_getters.h
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/java_bindings_getters.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef COMPONENTS_ADBLOCK_ANDROID_JAVA_BINDINGS_GETTERS_H_
+#define COMPONENTS_ADBLOCK_ANDROID_JAVA_BINDINGS_GETTERS_H_
+
+#include "components/adblock/android/adblock_jni.h"
+#include "components/adblock/android/filtering_configuration_bindings.h"
+#include "components/adblock/android/resource_classification_notifier_bindings.h"
+#include "components/adblock/core/subscription/subscription_service.h"
+
+namespace adblock {
+
+SubscriptionService* GetSubscriptionService();
+
+AdblockJNI* GetJNI();
+
+FilteringConfigurationBindings& GetFilteringConfigurationBindings();
+
+ResourceClassificationNotifierBindings&
+GetResourceClassificationNotifierBindings();
+
+int GetTabId(content::RenderFrameHost* render_frame_host);
+
+} // namespace adblock
+
+#endif // COMPONENTS_ADBLOCK_ANDROID_JAVA_BINDINGS_GETTERS_H_
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTestBase.java
@@ -0,0 +1,63 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.base.test.util.Feature;
+import org.chromium.base.test.util.IntegrationTest;
+import org.chromium.components.adblock.AdblockController;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public abstract class AdblockControllerTestBase {
+ private final CallbackHelper mHelper = new CallbackHelper();
+
+ @Test
+ @IntegrationTest
+ @LargeTest
+ @Feature({"adblock"})
+ public void addingAllowedDomains() throws TimeoutException {
+ final List<String> allowedDomains = new ArrayList<>();
+ TestThreadUtils.runOnUiThreadBlocking(() -> {
+ AdblockController.getInstance().addAllowedDomain("foobar.com");
+ AdblockController.getInstance().addAllowedDomain("domain.com/path/to/page.html");
+ AdblockController.getInstance().addAllowedDomain("domain.com/duplicate.html");
+ AdblockController.getInstance().addAllowedDomain("https://scheme.com/path.html");
+ AdblockController.getInstance().addAllowedDomain("gibberish");
+ allowedDomains.addAll(AdblockController.getInstance().getAllowedDomains());
+ mHelper.notifyCalled();
+ });
+ mHelper.waitForCallback(0, 1, 10, TimeUnit.SECONDS);
+ // We expect to see a sorted collection of domains (not URLs) without duplicates.
+ ArrayList<String> expectedAllowedDomains = new ArrayList<String>();
+ expectedAllowedDomains.add("domain.com");
+ expectedAllowedDomains.add("foobar.com");
+ expectedAllowedDomains.add("scheme.com");
+ expectedAllowedDomains.add("www.gibberish.com");
+ Assert.assertEquals(expectedAllowedDomains, allowedDomains);
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestAdBlockedObserver.java
@@ -0,0 +1,176 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import org.junit.Assert;
+
+import org.chromium.components.adblock.AdblockContentType;
+import org.chromium.components.adblock.AdblockCounters;
+import org.chromium.components.adblock.ResourceClassificationNotifier;
+
+import java.net.URL;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.CountDownLatch;
+
+public class TestAdBlockedObserver implements ResourceClassificationNotifier.AdBlockedObserver {
+ @Override
+ public void onAdAllowed(AdblockCounters.ResourceInfo info) {
+ allowedInfos.add(info);
+ Assert.assertEquals(info.getSubscription(), getExpectedSubscriptionUrl());
+ CheckAndCountDownLatch(Decision.ALLOWED, info.getRequestUrl().split("\\?")[0]);
+ }
+
+ @Override
+ public void onAdBlocked(AdblockCounters.ResourceInfo info) {
+ blockedInfos.add(info);
+ Assert.assertEquals(info.getSubscription(), getExpectedSubscriptionUrl());
+ CheckAndCountDownLatch(Decision.BLOCKED, info.getRequestUrl().split("\\?")[0]);
+ }
+
+ @Override
+ public void onPageAllowed(AdblockCounters.ResourceInfo info) {
+ allowedPageInfos.add(info);
+ Assert.assertEquals(info.getSubscription(), getExpectedSubscriptionUrl());
+ }
+
+ @Override
+ public void onPopupAllowed(AdblockCounters.ResourceInfo info) {
+ allowedPopupsInfos.add(info);
+ Assert.assertEquals(info.getSubscription(), getExpectedSubscriptionUrl());
+ }
+
+ @Override
+ public void onPopupBlocked(AdblockCounters.ResourceInfo info) {
+ blockedPopupsInfos.add(info);
+ Assert.assertEquals(info.getSubscription(), getExpectedSubscriptionUrl());
+ }
+
+ public boolean isBlocked(String url) {
+ for (AdblockCounters.ResourceInfo info : blockedInfos) {
+ if (info.getRequestUrl().contains(url)) return true;
+ }
+
+ return false;
+ }
+
+ public boolean isPopupBlocked(String url) {
+ for (AdblockCounters.ResourceInfo info : blockedPopupsInfos) {
+ if (info.getRequestUrl().contains(url)) return true;
+ }
+
+ return false;
+ }
+
+ public int numBlockedByType(AdblockContentType type) {
+ int result = 0;
+ for (AdblockCounters.ResourceInfo info : blockedInfos) {
+ if (info.getAdblockContentType() == type) ++result;
+ }
+ return result;
+ }
+
+ public int numBlockedPopups() {
+ return blockedPopupsInfos.size();
+ }
+
+ public boolean isAllowed(String url) {
+ for (AdblockCounters.ResourceInfo info : allowedInfos) {
+ if (info.getRequestUrl().contains(url)) return true;
+ }
+
+ return false;
+ }
+
+ public boolean isPageAllowed(String url) {
+ for (AdblockCounters.ResourceInfo info : allowedPageInfos) {
+ if (info.getRequestUrl().contains(url)) return true;
+ }
+
+ return false;
+ }
+
+ public boolean isPopupAllowed(String url) {
+ for (AdblockCounters.ResourceInfo info : allowedPopupsInfos) {
+ if (info.getRequestUrl().contains(url)) return true;
+ }
+
+ return false;
+ }
+
+ public int numAllowedByType(AdblockContentType type) {
+ int result = 0;
+ for (AdblockCounters.ResourceInfo info : allowedInfos) {
+ if (info.getAdblockContentType() == type) ++result;
+ }
+ return result;
+ }
+
+ public int numAllowedPopups() {
+ return allowedPopupsInfos.size();
+ }
+
+ public void setExpectedSubscriptionUrl(URL url) {
+ mTestSubscriptionUrl = url;
+ }
+
+ private String getExpectedSubscriptionUrl() {
+ if (mTestSubscriptionUrl != null) return mTestSubscriptionUrl.toString();
+ return "adblock:custom";
+ }
+
+ private enum Decision { ALLOWED, BLOCKED }
+
+ // We either countDown() our latch for every filtered resource if there are no
+ // specific expectations set (expectedAllowed == null && expectedBlocked == null),
+ // or we countDown() only when all expectations have been met so when:
+ // (expectedAllowed.isNullOrEmpty() && expectedBlocked.isNullOrEmpty()).
+ private void CheckAndCountDownLatch(final Decision decision, final String url) {
+ if (countDownLatch != null) {
+ if (expectedBlocked == null && expectedAllowed == null) {
+ countDownLatch.countDown();
+ } else {
+ if (decision == Decision.BLOCKED) {
+ if (expectedBlocked != null) {
+ expectedBlocked.remove(url);
+ }
+ } else {
+ if (expectedAllowed != null) {
+ expectedAllowed.remove(url);
+ }
+ }
+ boolean expectationsMet = (expectedAllowed == null || expectedAllowed.isEmpty())
+ && (expectedBlocked == null || expectedBlocked.isEmpty());
+ if (expectationsMet) {
+ countDownLatch.countDown();
+ }
+ }
+ }
+ }
+
+ private URL mTestSubscriptionUrl;
+ public List<AdblockCounters.ResourceInfo> blockedInfos = new CopyOnWriteArrayList<>();
+ public List<AdblockCounters.ResourceInfo> allowedInfos = new CopyOnWriteArrayList<>();
+ public List<AdblockCounters.ResourceInfo> allowedPageInfos = new CopyOnWriteArrayList<>();
+ public List<AdblockCounters.ResourceInfo> blockedPopupsInfos = new CopyOnWriteArrayList<>();
+ public List<AdblockCounters.ResourceInfo> allowedPopupsInfos = new CopyOnWriteArrayList<>();
+ CountDownLatch countDownLatch;
+ Set<String> expectedAllowed;
+ Set<String> expectedBlocked;
+};
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTestBase.java
@@ -0,0 +1,64 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.chromium.base.test.util.Feature;
+import org.chromium.content_public.browser.test.util.JavaScriptUtils;
+
+public abstract class TestPagesCircumventionTestBase {
+ private TestPagesHelperBase mHelper;
+
+ public void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ mHelper.addFilterList(TestPagesHelperBase.TESTPAGES_SUBSCRIPTION);
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyCircumventionInlineStyleNotImportant() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.CIRCUMVENTION_TESTPAGES_TESTCASES_ROOT
+ + "inline-style-important");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 2, "div");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyCircumventionAnonymousFrameDocumentWrite() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.CIRCUMVENTION_TESTPAGES_TESTCASES_ROOT
+ + "anoniframe-documentwrite");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "span[data-expectedresult='fail']");
+ String numHidden = JavaScriptUtils.executeJavaScriptAndWaitForResult(
+ mHelper.getWebContents(),
+ "var hiddenCount = 0;"
+ + "var elements = document.getElementById(\"write\").contentWindow"
+ + ".document.getElementsByTagName(\"span\");"
+ + "for (let i = 0; i < elements.length; ++i) {"
+ + " if (window.getComputedStyle(elements[i]).display == \"none\") "
+ + "++hiddenCount;"
+ + "}"
+ + "hiddenCount;");
+ Assert.assertEquals("1", numHidden);
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTestBase.java
@@ -0,0 +1,108 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Test;
+
+import org.chromium.base.test.util.Feature;
+
+public abstract class TestPagesCspTestBase {
+ private TestPagesHelperBase mHelper;
+
+ protected void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testCspAllSites() throws Exception {
+ mHelper.addCustomFilter("*$csp=script-src 'none'");
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "csp_all");
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 0, "img[id='all-sites-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testCspSpecificSite() throws Exception {
+ mHelper.addCustomFilter(String.format("||%s^$csp=script-src https://%s/lib/utils.js",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "csp_specific");
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 0, "img[id='specific-site-fail-1']",
+ TestVerificationUtils.IncludeSubframes.NO);
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testCspSpecificSiteFrameSrc() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("||%s^$csp=frame-src 'self'", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "csp_specific");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div[id='sub-frame-error']", TestVerificationUtils.IncludeSubframes.NO);
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 0, "div[id='sub-frame-error-details']",
+ TestVerificationUtils.IncludeSubframes.NO);
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testCspException() throws Exception {
+ // Blocking filter:
+ mHelper.addCustomFilter(String.format("||%s^$csp=script-src https://%s/lib/utils.js",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ // Resource loaded by JS was blocked
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div[id='unblock-javascript'] > img");
+
+ // Allowing filter:
+ mHelper.addCustomFilter(String.format("@@||%s^$csp", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ // Resource loaded by JS was allowed
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div[id='unblock-javascript'] > img");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testCspGenericBlockException() throws Exception {
+ // Blocking filter:
+ mHelper.addCustomFilter(String.format("||%s^$csp=script-src https://%s/lib/utils.js",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ // Resource loaded by JS was blocked
+ mHelper.loadUrl(
+ TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp_genericblock");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div[id='genericblock-javascript'] > img");
+
+ // Allowing filter:
+ mHelper.addCustomFilter(
+ String.format("@@||%s^$genericblock", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ // Resource loaded by JS was allowed
+ mHelper.loadUrl(
+ TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "csp_genericblock");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div[id='genericblock-javascript'] > img");
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTestBase.java
@@ -0,0 +1,135 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Test;
+
+import org.chromium.base.test.util.Feature;
+
+public abstract class TestPagesElemhideEmuInvTestBase {
+ public static final String ELEMENT_HIDING_EMULATION_TESTPAGES_URL =
+ TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT
+ + "element-hiding-emulation-inversion";
+ private TestPagesHelperBase mHelper;
+
+ protected void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuNotAbpProperties() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#?#.ehei-properties:not(:-abp-properties(width: 238px))",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='basic-not-abp-properties-usage-fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuNotAbpHas() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#?#.ehei-has:not(:-abp-has(span.ehei-has-not-hide))",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='basic-not-abp-has-usage-fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuNotAbpContains() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#?#.ehei-contains:not(span:-abp-contains(example-content))",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "span[id='basic-not-abp-contains-usage-fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuNotChained() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#?#.ehei-chained-parent:not(:-abp-has(> div:-abp-properties(width: 198px)))",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='chained-extended-selectors-with-not-selector-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuNotCaseIsensitive() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#?#.ehei-case:not(:-abp-properties(WiDtH: 209px))",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='case-insensitive-extended-selectors-with-not-selector-fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuNotWildcard() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#?#.ehei-wildcard:not(:-abp-properties(cursor:*))",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1,
+ "div[id='wildcard-in-extended-selector-combined-with-not-selector-fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuNotRegexAbpProperties() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#?#.ehei-regex:not(:-abp-properties(/width: 11[1-5]px;/))",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='regular-expression-in-not-abp-properties-fail-1']");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='regular-expression-in-not-abp-properties-fail-2']");
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 1, ".ehei-regex3");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuNotRegexAbpContains() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#?#.ehei-contains-regex:not(span:-abp-contains(/example-contentregex\\d/))",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "span[id='regular-expression-in-not-abp-contains-fail-1']");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "span[id='regular-expression-in-not-abp-contains-fail-2']");
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 2, ".ehei-contains-regex");
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTestBase.java
@@ -0,0 +1,183 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Test;
+
+import org.chromium.base.test.util.Feature;
+
+public abstract class TestPagesElemhideEmuTestBase {
+ public static final String ELEMENT_HIDING_EMULATION_TESTPAGES_URL =
+ TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "element-hiding-emulation";
+ public static final String ELEMENT_HIDING_EMULATION_EXCEPTIONS_TESTPAGES_URL =
+ TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "element-hiding";
+ private TestPagesHelperBase mHelper;
+
+ protected void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersBasicAbpProperties() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#?#div:-abp-properties(width: 213px)", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='basic-abp-properties-usage-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersBasicAbpHas() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#?#div:-abp-has(>div>span.ehe-abp-has)", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[id='basic-abp-has-usage-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersBasicHas() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#?#div:has(>div>span.ehe-has)", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ // "Basic :has() usage" are duplicated on testpage.
+ TestVerificationUtils.verifyHiddenCount(mHelper, 2, "div[id='basic-has-usage-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersBasicAbpContains() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#?#span:-abp-contains(ehe-contains-target)",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "span[id='basic-abp-contains-usage-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersBasicXpath() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#?#span:xpath(//*[@id=\"basic-xpath-usage-fail\"])",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "span[id='basic-xpath-usage-fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersBasicHasText() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#?#span:has-text(ehe-has-text)", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "span[id='basic-has-text-usage-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersChainedExtendedSelectors() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#?#div:-abp-has(> div:-abp-properties(width: 214px))",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='chained-extended-selectors-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersCaseInsensitiveExtendedSelectors() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#?#div:-abp-properties(WiDtH: 215px)", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='case-insensitive-extended-selectors-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersWildcardInExtendedSelector() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#?#div:-abp-properties(cursor:*)", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='wildcard-in-extended-selector-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersRegularExpressionInAbpProperties() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#?#div:-abp-properties(/width: 12[1-5]px;/)",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='regular-expression-in-abp-properties-fail-1']");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='regular-expression-in-abp-properties-fail-2']");
+ // "Not a target" div is not hidden, does not match regular expression.
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div[class='testcase-examplecontent ehe-regex3']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersRegularExpressionInAbpContains() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#?#div > div:-abp-contains(/ehe-containsregex\\d/)",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='regular-expression-in-abp-contains-fail-1']");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='regular-expression-in-abp-contains-fail-2']");
+ }
+
+ // Exceptions:
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideEmuFiltersException() throws Exception {
+ // Add a blocking filter, verify element hidden.
+ mHelper.addCustomFilter(
+ String.format("%s##.testcase-ehe", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_EXCEPTIONS_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[id='exception-usage-pass-1']");
+
+ // Add exception filter, verify element no longer hidden.
+ mHelper.addCustomFilter(
+ String.format("%s#@#.testcase-ehe", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EMULATION_EXCEPTIONS_TESTPAGES_URL);
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 1, "div[id='exception-usage-pass-1']");
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTestBase.java
@@ -0,0 +1,204 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Test;
+
+import org.chromium.base.test.util.Feature;
+
+public abstract class TestPagesElemhideTestBase {
+ public static final String ELEMENT_HIDING_TESTPAGES_URL =
+ TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "element-hiding";
+ public static final String ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL =
+ TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "elemhide";
+ private TestPagesHelperBase mHelper;
+
+ protected void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersIdSelector() throws Exception {
+ mHelper.addCustomFilter(String.format("%s###eh-id", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[id='eh-id']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersIdSelectorDoubleCurlyBraces() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s##div[id='{{eh-id}}']", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[id='{{eh-id}}']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersClassSelector() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s##.eh-class", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[class='eh-class']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersDescendantSelector() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s##.testcase-area > .eh-descendant", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[class='eh-descendant']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersSiblingSelector() throws Exception {
+ mHelper.addCustomFilter(String.format("%s##.testcase-examplecontent + .eh-sibling",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[class='eh-sibling']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersAttributeSelector1() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s##div[height=\"100\"][width=\"100\"]", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='attribute-selector-1-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersAttributeSelector2() throws Exception {
+ mHelper.addCustomFilter(String.format("%s##div[href=\"http://testcase-attribute.com/\"]",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='attribute-selector-2-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersAttributeSelector3() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s##div[style=\"width: 200px;\"]", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='attribute-selector-3-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersStartsWithSelector1() throws Exception {
+ mHelper.addCustomFilter(String.format("%s##div[href^=\"http://testcase-startswith.com/\"]",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='starts-with-selector-1-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersStartsWithSelector2() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s##div[style^=\"width: 201px;\"]", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='starts-with-selector-2-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersEndsWithSelector1() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s##div[style$=\"width: 202px;\"]", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div[id='ends-with-selector-1-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersContains() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s##div[style*=\"width: 203px;\"]", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[id='contains-fail-1']");
+ }
+
+ // Exceptions:
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersBasicException() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s##.ex-elemhide", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/elemhide/basic/*", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL);
+ // No exceptions added yet, both objects should be blocked.
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "img[id='basic-usage-fail-1']");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[id='basic-usage-pass-1']");
+ // Add exception filter and reload.
+ mHelper.addCustomFilter(String.format(
+ "@@%s/en/exceptions/elemhide$elemhide", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL);
+ // Image should remain blocked, div should be unblocked.
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "img[id='basic-usage-fail-1']");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div[id='basic-usage-area'] > div[id='basic-usage-pass-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testElemHideFiltersIframeException() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s##.targ-elemhide", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/elemhide/iframe/*.png", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "img[id='iframe-fail-1']");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[id='iframe-pass-1']");
+
+ // Add exception filter and reload.
+ mHelper.addCustomFilter(String.format(
+ "@@%s/en/exceptions/elemhide$elemhide", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(ELEMENT_HIDING_EXCEPTIONS_TESTPAGES_URL);
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "img[id='iframe-fail-1']");
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 1, "div[id='iframe-pass-1']");
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTestBase.java
@@ -0,0 +1,174 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.chromium.base.test.util.Feature;
+import org.chromium.components.adblock.AdblockContentType;
+import org.chromium.content_public.browser.test.util.JavaScriptUtils;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public abstract class TestPagesExceptionTestBase {
+ private TestPagesHelperBase mHelper;
+
+ protected void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ mHelper.addFilterList(TestPagesHelperBase.TESTPAGES_SUBSCRIPTION);
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyImageExceptions() throws Exception {
+ final String subdomainImage = String.format(
+ "https://allowed.subdomain.%s/testfiles/image_exception/subdomain.png",
+ TestPagesHelperBase.TESTPAGES_DOMAIN);
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "image");
+ Assert.assertEquals(2, mHelper.numAllowed());
+ Assert.assertEquals(2, mHelper.numAllowedByType(AdblockContentType.CONTENT_TYPE_IMAGE));
+ Assert.assertTrue(mHelper.isAllowed(subdomainImage));
+ Assert.assertTrue(mHelper.isAllowed(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "image_exception/image.png"));
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 2, "img");
+ String numImages = JavaScriptUtils.executeJavaScriptAndWaitForResult(
+ mHelper.getWebContents(), "document.getElementsByTagName(\"img\").length;");
+ Assert.assertEquals("2", numImages);
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifySubdocumentException() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "subdocument");
+ Assert.assertEquals(1, mHelper.numAllowed());
+ Assert.assertTrue(mHelper.isAllowed(TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT
+ + "subdocument_exception/subdocument.html"));
+ TestVerificationUtils.verifyGreenBackground(mHelper, "exception-target");
+ String numFrames = JavaScriptUtils.executeJavaScriptAndWaitForResult(
+ mHelper.getWebContents(), "window.frames.length;");
+ Assert.assertEquals("1", numFrames);
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 1, "iframe");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyScriptException() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "script");
+ Assert.assertEquals(1, mHelper.numAllowed());
+ Assert.assertTrue(mHelper.isAllowed(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "script_exception/script.js"));
+ TestVerificationUtils.verifyGreenBackground(mHelper, "script-target");
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "script_exception/image.png"));
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "img[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyStylesheetException() throws Exception {
+ final String allowedUrl =
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "stylesheet_exception/stylesheet.cs";
+ final CountDownLatch countDownLatch =
+ mHelper.setOnAdMatchedExpectations(null, new HashSet<>(List.of(allowedUrl)));
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "stylesheet");
+ // Wait with 10 seconds max timeout
+ countDownLatch.await(10, TimeUnit.SECONDS);
+ Assert.assertEquals(1, mHelper.numAllowed());
+ Assert.assertTrue(mHelper.isAllowed(allowedUrl));
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "stylesheet_exception/image.png"));
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "img");
+ TestVerificationUtils.verifyGreenBackground(mHelper, "exception-target");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyXHRException() throws Exception {
+ final String allowedUrl =
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "xmlhttprequest_exception/text.txt";
+ final CountDownLatch countDownLatch =
+ mHelper.setOnAdMatchedExpectations(null, new HashSet<>(List.of(allowedUrl)));
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "xmlhttprequest");
+ // Wait with 10 seconds max timeout
+ countDownLatch.await(10, TimeUnit.SECONDS);
+ Assert.assertEquals(1, mHelper.numAllowed());
+ Assert.assertTrue(mHelper.isAllowed(allowedUrl));
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyGenericBlockException() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "genericblock");
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "genericblock/specific.png"));
+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE));
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 1, "img[data-expectedresult='pass']");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "img[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyGenericHideException() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "generichide");
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 1, "div[data-expectedresult='pass']");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyDocumentException() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "document");
+ Assert.assertTrue(mHelper.isAllowed(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "document/image.png"));
+ Assert.assertTrue(mHelper.isPageAllowed(
+ TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "document"));
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 1, "div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyWebSocketException() throws Exception {
+ final String wssUrl =
+ String.format("wss://%s/websocket", TestPagesHelperBase.TESTPAGES_DOMAIN);
+ final CountDownLatch countDownLatch =
+ mHelper.setOnAdMatchedExpectations(null, new HashSet<>(List.of(wssUrl)));
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "websocket");
+ // Wait with 10 seconds max timeout
+ countDownLatch.await(10, TimeUnit.SECONDS);
+ Assert.assertEquals(1, mHelper.numAllowedByType(AdblockContentType.CONTENT_TYPE_WEBSOCKET));
+ Assert.assertTrue(mHelper.isAllowed(wssUrl));
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTestBase.java
@@ -0,0 +1,254 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.chromium.base.test.util.DisabledTest;
+import org.chromium.base.test.util.Feature;
+import org.chromium.components.adblock.AdblockContentType;
+import org.chromium.content_public.browser.test.util.DOMUtils;
+import org.chromium.content_public.browser.test.util.JavaScriptUtils;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public abstract class TestPagesFilterTestBase {
+ private TestPagesHelperBase mHelper;
+
+ protected void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ mHelper.addFilterList(TestPagesHelperBase.TESTPAGES_SUBSCRIPTION);
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testBlockingFilters() throws Exception {
+ final CountDownLatch countDownLatch = mHelper.setOnAdMatchedExpectations(
+ new HashSet<>(Arrays.asList(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "blocking/full-path.png",
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT
+ + "blocking/partial-path/partial-path.png",
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT
+ + "blocking/wildcard/1/wildcard.png",
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT
+ + "blocking/wildcard/2/wildcard.png",
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "blocking/dynamic.png",
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "blocking/subdomain.png")),
+ null);
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "blocking");
+ // Wait with 10 seconds max timeout
+ countDownLatch.await(10, TimeUnit.SECONDS);
+ Assert.assertEquals(6, mHelper.numBlocked());
+ Assert.assertEquals(6, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE));
+ TestVerificationUtils.verifyHiddenCount(mHelper, 6, "img[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyScriptFilters() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "script");
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SCRIPT));
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "script/script.js"));
+
+ String childCount =
+ JavaScriptUtils.executeJavaScriptAndWaitForResult(mHelper.getWebContents(),
+ "document.getElementById(\"script-target\").childElementCount");
+ Assert.assertEquals("1", childCount);
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyImageFilters() throws Exception {
+ final CountDownLatch countDownLatch = mHelper.setOnAdMatchedExpectations(
+ new HashSet<>(Arrays.asList(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "image/static/static.png",
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT
+ + "image/dynamic/dynamic.png")),
+ null);
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "image");
+ countDownLatch.await(10, TimeUnit.SECONDS);
+ Assert.assertEquals(2, mHelper.numBlocked());
+ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE));
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "image/static/static.png"));
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "image/dynamic/dynamic.png"));
+ TestVerificationUtils.verifyHiddenCount(mHelper, 2, "img[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyStylesheetFilters() throws Exception {
+ final String blockedUrl =
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "stylesheet/stylesheet.cs";
+ final CountDownLatch countDownLatch =
+ mHelper.setOnAdMatchedExpectations(new HashSet<>(List.of(blockedUrl)), null);
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "stylesheet");
+ // Wait with 10 seconds max timeout
+ countDownLatch.await(10, TimeUnit.SECONDS);
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertEquals(
+ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_STYLESHEET));
+ Assert.assertTrue(mHelper.isBlocked(blockedUrl));
+ String value = DOMUtils.getNodeContents(mHelper.getWebContents(), "stylesheet-target");
+ Assert.assertEquals("Passed. Stylesheet was blocked.", value);
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyXHRFilters() throws Exception {
+ final String blockedUrl =
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "xmlhttprequest/text.txt";
+ final CountDownLatch countDownLatch =
+ mHelper.setOnAdMatchedExpectations(new HashSet<>(List.of(blockedUrl)), null);
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "xmlhttprequest");
+ // Wait with 10 seconds max timeout
+ countDownLatch.await(10, TimeUnit.SECONDS);
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertEquals(
+ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_XMLHTTPREQUEST));
+ Assert.assertTrue(mHelper.isBlocked(blockedUrl));
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifySubdocumentFilters() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "subdocument");
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertEquals(
+ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SUBDOCUMENT));
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "subdocument/subdocument.html"));
+ // Do not search for iframe within the site's iframes.
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "iframe[data-expectedresult='fail']",
+ TestVerificationUtils.IncludeSubframes.NO);
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ @DisabledTest(message = "Please enable again when rewrite filters will be supported")
+ public void testVerifyRewrite() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "rewrite");
+ Assert.assertEquals(3, mHelper.numBlocked());
+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SCRIPT));
+ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_MEDIA));
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "rewrite/audio.mp3"));
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "rewrite/video.mp4"));
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "rewrite/script.js"));
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyMatchCaseFilter() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "match-case");
+ Assert.assertEquals(2, mHelper.numBlocked());
+ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE));
+ TestVerificationUtils.verifyHiddenCount(mHelper, 2, "img[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyThirdPartyFilter() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "third-party");
+ Assert.assertEquals(2, mHelper.numBlocked());
+ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE));
+ TestVerificationUtils.verifyHiddenCount(mHelper, 2, "img[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 2, "img[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyOtherFilter() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "other");
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_OTHER));
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "other/image.png"));
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyDomainFilter() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "domain");
+ Assert.assertEquals(2, mHelper.numBlocked());
+ Assert.assertEquals(2, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE));
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "domain/static/target/image.png"));
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "domain/dynamic/image.png"));
+ TestVerificationUtils.verifyHiddenCount(mHelper, 2, "img[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyPingFilter() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "ping");
+ // Ping action not yet triggered
+ Assert.assertEquals(0, mHelper.numBlocked());
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ mHelper.setOnAdMatchedLatch(countDownLatch);
+ // Trigger ping action
+ JavaScriptUtils.executeJavaScriptAndWaitForResult(mHelper.getWebContents(),
+ "document.getElementById(\"script-ping-trigger\").click()");
+ // Wait with 10 seconds max timeout
+ countDownLatch.await(10, TimeUnit.SECONDS);
+ Assert.assertEquals(1, mHelper.numBlocked());
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyPingFilterException() throws Exception {
+ mHelper.loadUrl(TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "ping");
+ // Ping action not yet triggered
+ Assert.assertEquals(0, mHelper.numAllowed());
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ mHelper.setOnAdMatchedLatch(countDownLatch);
+ // Trigger ping action
+ JavaScriptUtils.executeJavaScriptAndWaitForResult(mHelper.getWebContents(),
+ "document.getElementsByClassName(\"testcase-trigger\")[0].click()");
+ // Wait with 10 seconds max timeout
+ countDownLatch.await(10, TimeUnit.SECONDS);
+ Assert.assertEquals(1, mHelper.numAllowed());
+ Assert.assertEquals(0, mHelper.numBlocked());
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTestBase.java
@@ -0,0 +1,125 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.chromium.base.test.util.Feature;
+import org.chromium.components.adblock.AdblockContentType;
+
+public abstract class TestPagesHeaderFilterTestBase {
+ public static final String HEADER_TESTPAGES_URL =
+ TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "header";
+ public static final String HEADER_EXCEPTIONS_TESTPAGES_URL =
+ TestPagesHelperBase.EXCEPTION_TESTPAGES_TESTCASES_ROOT + "header";
+ private TestPagesHelperBase mHelper;
+
+ protected void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHeaderFilterScript() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("||%s/testfiles/header/$header=content-type=application/javascript",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(HEADER_TESTPAGES_URL);
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_SCRIPT));
+ Assert.assertTrue(mHelper.isBlocked(String.format(
+ "https://%s/testfiles/header/script.js", TestPagesHelperBase.TESTPAGES_DOMAIN)));
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#functionproperty-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHeaderFilterImage() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("||%s/testfiles/header/image.png$header=content-type=image/png",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(HEADER_TESTPAGES_URL);
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE));
+ Assert.assertTrue(mHelper.isBlocked(String.format(
+ "https://%s/testfiles/header/image.png", TestPagesHelperBase.TESTPAGES_DOMAIN)));
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 0, "img[id='image-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHeaderFilterImageAndComma() throws Exception {
+ mHelper.addCustomFilter(String.format("||%s/testfiles/header/image2.png$header=date=\\x2c",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(HEADER_TESTPAGES_URL);
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE));
+ Assert.assertTrue(mHelper.isBlocked(String.format(
+ "https://%s/testfiles/header/image2.png", TestPagesHelperBase.TESTPAGES_DOMAIN)));
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 0, "img[id='comma-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHeaderFilterStylesheet() throws Exception {
+ mHelper.addCustomFilter(String.format("||%s/testfiles/header/$header=content-type=text/css",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(HEADER_TESTPAGES_URL);
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertEquals(
+ 1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_STYLESHEET));
+ Assert.assertTrue(
+ mHelper.isBlocked(String.format("https://%s/testfiles/header/stylesheet.css",
+ TestPagesHelperBase.TESTPAGES_DOMAIN)));
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHeaderFilterException() throws Exception {
+ // Add blocking filter, expect blocked image
+ mHelper.addCustomFilter(
+ String.format("||%s/testfiles/header_exception/$header=content-type=image/png",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(HEADER_EXCEPTIONS_TESTPAGES_URL);
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_IMAGE));
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "img[id='image-header-exception-pass-1']");
+
+ // Add exception filter, expect image allowed
+ mHelper.addCustomFilter(String.format(
+ "@@%s/testfiles/header_exception/$header", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(HEADER_EXCEPTIONS_TESTPAGES_URL);
+ Assert.assertEquals(1, mHelper.numAllowed());
+ Assert.assertEquals(1, mHelper.numAllowedByType(AdblockContentType.CONTENT_TYPE_IMAGE));
+ Assert.assertTrue(
+ mHelper.isAllowed(String.format("https://%s/testfiles/header_exception/image.png",
+ TestPagesHelperBase.TESTPAGES_DOMAIN)));
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "img[id='image-header-exception-pass-1']");
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHelperBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHelperBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHelperBase.java
@@ -0,0 +1,180 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import org.junit.Assert;
+
+import org.chromium.base.Log;
+import org.chromium.base.test.util.CallbackHelper;
+import org.chromium.components.adblock.AdblockContentType;
+import org.chromium.components.adblock.AdblockController;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+public abstract class TestPagesHelperBase {
+ public static final String TESTPAGES_DOMAIN = "abptestpages.org";
+ public static final String TESTPAGES_BASE_URL = "https://" + TESTPAGES_DOMAIN;
+ public static final String TESTPAGES_TESTCASES_ROOT = TESTPAGES_BASE_URL + "/en/";
+ public static final String FILTER_TESTPAGES_TESTCASES_ROOT =
+ TESTPAGES_TESTCASES_ROOT + "filters/";
+ public static final String EXCEPTION_TESTPAGES_TESTCASES_ROOT =
+ TESTPAGES_TESTCASES_ROOT + "exceptions/";
+ public static final String CIRCUMVENTION_TESTPAGES_TESTCASES_ROOT =
+ TESTPAGES_TESTCASES_ROOT + "circumvention/";
+ public static final String SITEKEY_TESTPAGES_TESTCASES_ROOT =
+ EXCEPTION_TESTPAGES_TESTCASES_ROOT + "sitekey";
+ public static final String SNIPPETS_TESTPAGES_TESTCASES_ROOT =
+ TESTPAGES_TESTCASES_ROOT + "snippets/";
+ public static final String TESTPAGES_RESOURCES_ROOT = TESTPAGES_BASE_URL + "/testfiles/";
+ public static final String TESTPAGES_SUBSCRIPTION =
+ TESTPAGES_TESTCASES_ROOT + "/abp-testcase-subscription.txt";
+ public static final int TEST_TIMEOUT_SEC = 30;
+
+ private URL mTestSubscriptionUrl;
+ private final CallbackHelper mHelper = new CallbackHelper();
+ private final TestAdBlockedObserver mObserver = new TestAdBlockedObserver();
+ private final TestSubscriptionUpdatedObserver mSubscriptionUpdateObserver =
+ new TestSubscriptionUpdatedObserver();
+
+ private class TestSubscriptionUpdatedObserver
+ implements AdblockController.SubscriptionUpdateObserver {
+ @Override
+ public void onSubscriptionDownloaded(final URL url) {
+ if (mTestSubscriptionUrl == null) return;
+ if (url.toString().contains(mTestSubscriptionUrl.toString())) {
+ Log.d("TestSubscriptionUpdatedObserver",
+ "Notify subscription updated: " + url.toString());
+ mHelper.notifyCalled();
+ }
+ }
+ }
+
+ public void setUp() {
+ TestThreadUtils.runOnUiThreadBlocking(() -> {
+ AdblockController.getInstance().addOnAdBlockedObserver(mObserver);
+ AdblockController.getInstance().addSubscriptionUpdateObserver(
+ mSubscriptionUpdateObserver);
+ });
+ }
+
+ public void addFilterList(final String filterListUrl) {
+ try {
+ mTestSubscriptionUrl = new URL(filterListUrl);
+ mObserver.setExpectedSubscriptionUrl(mTestSubscriptionUrl);
+ } catch (MalformedURLException ignored) {
+ }
+ Assert.assertNotNull("Test subscription url", mTestSubscriptionUrl);
+ TestThreadUtils.runOnUiThreadBlocking(() -> {
+ AdblockController.getInstance().installSubscription(mTestSubscriptionUrl);
+ });
+ try {
+ mHelper.waitForCallback(0, 1, TEST_TIMEOUT_SEC, TimeUnit.SECONDS);
+ } catch (TimeoutException e) {
+ Assert.assertEquals(
+ "Test subscription was properly added", "Failed to add test subscription");
+ }
+ }
+
+ public void addCustomFilter(final String filter) {
+ TestThreadUtils.runOnUiThreadBlocking(
+ () -> { AdblockController.getInstance().addCustomFilter(filter); });
+ }
+
+ public void tearDown() {
+ TestThreadUtils.runOnUiThreadBlocking(() -> {
+ AdblockController.getInstance().removeSubscriptionUpdateObserver(
+ mSubscriptionUpdateObserver);
+ AdblockController.getInstance().removeOnAdBlockedObserver(mObserver);
+ });
+ }
+
+ // Note: Use either setOnAdMatchedLatch XOR setOnAdMatchedExpectations
+ public void setOnAdMatchedLatch(final CountDownLatch countDownLatch) {
+ Assert.assertTrue(
+ mObserver.countDownLatch == null || mObserver.countDownLatch.getCount() == 0);
+ mObserver.countDownLatch = countDownLatch;
+ }
+
+ // Note: Use either setOnAdMatchedLatch XOR setOnAdMatchedExpectations
+ public CountDownLatch setOnAdMatchedExpectations(
+ final Set<String> onBlocked, final Set<String> onAllowed) {
+ Assert.assertTrue(
+ mObserver.countDownLatch == null || mObserver.countDownLatch.getCount() == 0);
+ mObserver.countDownLatch = new CountDownLatch(1);
+ mObserver.expectedBlocked = onBlocked;
+ mObserver.expectedAllowed = onAllowed;
+ return mObserver.countDownLatch;
+ }
+
+ public boolean isBlocked(final String url) {
+ return mObserver.isBlocked(url);
+ }
+
+ public boolean isPopupBlocked(final String url) {
+ return mObserver.isPopupBlocked(url);
+ }
+
+ public int numBlockedByType(final AdblockContentType type) {
+ return mObserver.numBlockedByType(type);
+ }
+
+ public int numBlockedPopups() {
+ return mObserver.numBlockedPopups();
+ }
+
+ public int numAllowedByType(final AdblockContentType type) {
+ return mObserver.numAllowedByType(type);
+ }
+
+ public int numAllowedPopups() {
+ return mObserver.numAllowedPopups();
+ }
+
+ public boolean isAllowed(final String url) {
+ return mObserver.isAllowed(url);
+ }
+
+ public boolean isPageAllowed(final String url) {
+ return mObserver.isPageAllowed(url);
+ }
+
+ public boolean isPopupAllowed(final String url) {
+ return mObserver.isPopupAllowed(url);
+ }
+
+ public abstract void loadUrl(final String url) throws Exception;
+
+ public abstract void loadUrlWaitForContent(final String url) throws Exception;
+
+ public abstract WebContents getWebContents();
+
+ public int numBlocked() {
+ return mObserver.blockedInfos.size();
+ }
+
+ public int numAllowed() {
+ return mObserver.allowedInfos.size();
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTestBase.java
@@ -0,0 +1,153 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.chromium.base.test.util.Feature;
+import org.chromium.content_public.browser.test.util.JavaScriptUtils;
+
+public abstract class TestPagesRewriteTestBase {
+ public static final String REWRITE_TEST_URL =
+ TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "rewrite";
+ private TestPagesHelperBase mHelper;
+
+ protected void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testRewriteScript() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/rewrite/*.js$rewrite=abp-resource:blank-js,domain=%s",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(REWRITE_TEST_URL);
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 0, "div[id='script-fail-1']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testRewriteStylesheet() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/rewrite/*.css$rewrite=abp-resource:blank-css,domain=%s",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(REWRITE_TEST_URL);
+ TestVerificationUtils.verifyGreenBackground(mHelper, "stylesheet-target");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testRewriteSubdocument() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/rewrite/*.html$rewrite=abp-resource:blank-html,domain=%s",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(REWRITE_TEST_URL);
+ TestVerificationUtils.verifySelfTestPass(mHelper, "subdocument-target");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testRewriteText() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/rewrite/*.txt$rewrite=abp-resource:blank-text,domain=%s",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(REWRITE_TEST_URL);
+ TestVerificationUtils.verifySelfTestPass(mHelper, "text-status");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testRewriteGif() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/rewrite/1x1.gif$rewrite=abp-resource:1x1-transparent-gif,domain=%s",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(REWRITE_TEST_URL);
+ TestVerificationUtils.verifySelfTestPass(mHelper, "1x1-target");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testRewrite2x2Png() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/rewrite/2x2.png$rewrite=abp-resource:2x2-transparent-png,domain=%s",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(REWRITE_TEST_URL);
+ TestVerificationUtils.verifySelfTestPass(mHelper, "2x2-target");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testRewrite3x2Png() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/rewrite/3x2.png$rewrite=abp-resource:3x2-transparent-png,domain=%s",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(REWRITE_TEST_URL);
+ TestVerificationUtils.verifySelfTestPass(mHelper, "3x2-target");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testRewrite32x32Png() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/rewrite/32x32.png$rewrite=abp-resource:32x32-transparent-png,"
+ + "domain=%s",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(REWRITE_TEST_URL);
+ TestVerificationUtils.verifySelfTestPass(mHelper, "32x32-target");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testRewriteAudio() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/rewrite/*.mp3$rewrite=abp-resource:blank-mp3,domain=%s",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(REWRITE_TEST_URL);
+ String value = JavaScriptUtils.executeJavaScriptAndWaitForResult(mHelper.getWebContents(),
+ "document.getElementById('audio-area').lastChild.getAttribute"
+ + "('data-expectedresult')");
+ Assert.assertEquals("\"pass\"", value);
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testRewriteVideo() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/rewrite/*.mp4$rewrite=abp-resource:blank-mp4,domain=%s",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrl(REWRITE_TEST_URL);
+ String value = JavaScriptUtils.executeJavaScriptAndWaitForResult(mHelper.getWebContents(),
+ "document.getElementById('video-area').lastChild.getAttribute"
+ + "('data-expectedresult')");
+ Assert.assertEquals("\"pass\"", value);
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTestBase.java
@@ -0,0 +1,58 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.chromium.base.test.util.Feature;
+
+public abstract class TestPagesSiteKeyTestBase {
+ private TestPagesHelperBase mHelper;
+
+ protected void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifySitekeyException() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#@#[data-adblockkey]", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.addCustomFilter(
+ String.format("%s##.testcase-sitekey-eh", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/sitekey/outofframe.png", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.addCustomFilter(String.format(
+ "||%s/testfiles/sitekey/inframe.png", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.addCustomFilter(
+ "@@$document,sitekey=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANGtTstne7e8MbmDHDiMFkGbcuBgXmiVesGOG3gtYeM1EkrzVhBjGUvKXYE4GLFwqty3v5MuWWbvItUWBTYoVVsCAwEAAQ");
+ mHelper.loadUrl(TestPagesHelperBase.SITEKEY_TESTPAGES_TESTCASES_ROOT);
+ Assert.assertEquals(1, mHelper.numBlocked());
+ Assert.assertTrue(mHelper.isBlocked(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "sitekey/outofframe.png"));
+ Assert.assertEquals(1, mHelper.numAllowed());
+ Assert.assertTrue(mHelper.isAllowed(
+ TestPagesHelperBase.TESTPAGES_RESOURCES_ROOT + "sitekey/inframe.png"));
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "img");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div");
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTestBase.java
@@ -0,0 +1,562 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Test;
+
+import org.chromium.base.test.util.Feature;
+
+public abstract class TestPagesSnippetsTestBase {
+ private TestPagesHelperBase mHelper;
+
+ protected void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortCurrentInlineScriptBasic() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#abort-current-inline-script console.group",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "abort-current-inline-script");
+ // All "Abort" snippets cancel creation of the target div, so it won't be hidden - it will
+ // not exist in DOM. Therefore we verify it's not displayed instead of verifying it's
+ // hidden.
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#basic-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortCurrentInlineScriptSearch() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#$#abort-current-inline-script console.info acis-search",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "abort-current-inline-script");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#search-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortCurrentInlineScriptRegex() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#$#abort-current-inline-script console.warn '/acis-regex[1-2]/'",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "abort-current-inline-script");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#regex-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnPropertyReadBasic() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#abort-on-property-read aoprb", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-read");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#basic-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnPropertyReadSubProperty() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#abort-on-property-read aopr.sp", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-read");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#subproperty-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnPropertyReadFunctionProperty() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#abort-on-property-read aoprf.fp", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-read");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#functionproperty-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnPropertyWriteBasic() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#abort-on-property-write window.aopwb", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-write");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#basic-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnPropertyWriteSubProperty() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#abort-on-property-write window.aopwsp",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-write");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#subproperty-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnPropertyWriteFunctionProperty() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#abort-on-property-write aopwf.fp", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "abort-on-property-write");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#functionproperty-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnIframePropertyReadBasic() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#abort-on-iframe-property-read aoiprb", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "abort-on-iframe-property-read");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#basic-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnIframePropertyReadSubProperty() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-read aoipr.sp",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "abort-on-iframe-property-read");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#subproperty-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnIframePropertyReadMultipleProperties() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-read aoipr1 aoipr2",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "abort-on-iframe-property-read");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#multipleproperties-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnIframePropertyWriteBasic() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-write aoipwb",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "abort-on-iframe-property-write");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#basic-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnIframePropertyWriteSubProperty() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-write aoipw.sp",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "abort-on-iframe-property-write");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#subproperty-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testAbortOnIframePropertyWriteMultipleProperties() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#abort-on-iframe-property-write aoipw1 aoipw2",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "abort-on-iframe-property-write");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#multipleproperties-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfContainsStatic() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains 'hic-basic-static' p[id]",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "p#hic-static-id");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfContainsDynamic() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains 'hic-basic-dynamic' p[id]",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "p#hic-dynamic-id");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfContainsSearch() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains 'hic-search' p[id] .target",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div#search2-target > p.target");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#search1-target > p[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfContainsRegex() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains /hic-regex-[2-3]/ p[id]",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains");
+ // "hic-regex-1" does not match regex, should remain displayed.
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 1, "p#hic-regex-1");
+
+ // "hic-regex-2" and "hic-regex-2" do match regex, should be hidden.
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "p#hic-regex-2");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "p#hic-regex-3");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfContainsFrame() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains hidden span#frame-target",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "span#frame-target");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfContainsAndMatchesStyleStatic() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#hide-if-contains-and-matches-style hicamss div[id] span.label /./ 'display:"
+ + " inline;'",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "hide-if-contains-and-matches-style");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#static-usage-area > div[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#static-usage-area > div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfContainsAndMatchesStyleDynamic() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#hide-if-contains-and-matches-style hicamsd div[id] span.label /./ 'display:"
+ + " inline;'",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "hide-if-contains-and-matches-style");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#dynamic-target > div[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#dynamic-target > div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfContainsImage() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#hide-if-contains-image "
+ + "/^89504e470d0a1a0a0000000d4948445200000064000000640802/ "
+ + "div[shouldhide] div",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-contains-image");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 2, "div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfContainsVisibleTextBasicUsage() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#hide-if-contains-visible-text Sponsored-hicvt-basic '#parent-basic > "
+ + ".article' '#parent-basic > .article .label'",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "hide-if-contains-visible-text");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#parent-basic > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfContainsVisibleTextContentUsage() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#hide-if-contains-visible-text Sponsored-hicvt-content '#parent-content > "
+ + ".article' '#parent-content > .article .label'",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "hide-if-contains-visible-text");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#parent-content > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfHasAndMatchesStyleBasicUsage() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#hide-if-has-and-matches-style a[href=\"#basic-target-ad\"] div[id] span"
+ + ".label /./ 'display: inline;'",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "hide-if-has-and-matches-style");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#basic-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfHasAndMatchesStyleLegitElements() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#hide-if-has-and-matches-style a[href=\"#comments-target-ad\"] div[id] span"
+ + ".label ';' /\\\\bdisplay:\\ inline\\;/",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "hide-if-has-and-matches-style");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#comments-target > div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfLabeledBy() throws Exception {
+ mHelper.addCustomFilter(String.format(
+ "%s#$#hide-if-labelled-by 'Label' '#hilb-target [aria-labelledby]' '#hilb-target'",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-labelled-by");
+ TestVerificationUtils.verifyHiddenCount(mHelper, 1, "div[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(mHelper, 1, "div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfMatchesXPathBasicStaticUsage() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#hide-if-matches-xpath //*[@id=\"isnfnv\"]",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#basic-static-usage-area > div[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#basic-static-usage-area > div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfMatchesXPath3BasicStaticUsage() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#hide-if-matches-xpath3 //*[@id=\"isnfnv\"]",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#basic-static-usage-area > div[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#basic-static-usage-area > div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfMatchesXPathClassUsage() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#$#hide-if-matches-xpath //*[@class=\"to-be-hidden\"]",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#class-usage-area > div[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#class-usage-area > div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfMatchesXPath3ClassUsage() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#$#hide-if-matches-xpath3 //*[@class=\"to-be-hidden\"]",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#class-usage-area > div[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#class-usage-area > div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfMatchesXPathIdStartsWith() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#$#hide-if-matches-xpath //div[starts-with(@id,\"fail\")]",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#hide-if-id-starts-with-area > div[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#hide-if-id-starts-with-area > div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfMatchesXPath3IdStartsWith() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#$#hide-if-matches-xpath3 //div[starts-with(@id,\"fail\")]",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-matches-xpath");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#hide-if-id-starts-with-area > div[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#hide-if-id-starts-with-area > div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfShadowContainsBasicUsage() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#hide-if-shadow-contains 'hisc-basic' p",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-shadow-contains");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#basic-target > p[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testHideIfShadowContainsRegexUsage() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#$#hide-if-shadow-contains '/hisc-regex[1-2]/' div",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "hide-if-shadow-contains");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 2, "div#regex-target > div[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#regex-target > div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testJsonPrune() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#$#json-prune 'data-expectedresult jsonprune aria-label'",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "json-prune?delay=100");
+ // The object does not get hidden, it no longer exists in the DOM.
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#testcase-area > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testOverridePropertyRead() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#$#override-property-read overridePropertyRead.fp false",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(
+ TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT + "override-property-read");
+ TestVerificationUtils.verifyHiddenCount(
+ mHelper, 1, "div#basic-target > div[data-expectedresult='fail']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testStripFetchQueryParameterBasicUsage() throws Exception {
+ mHelper.addCustomFilter(String.format("%s#$#strip-fetch-query-parameter basicBlocked %s",
+ TestPagesHelperBase.TESTPAGES_DOMAIN, TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "strip-fetch-query-parameter");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 0, "div#basic-target > div[data-expectedresult='fail']");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 1, "div#basic-target > div[data-expectedresult='pass']");
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testStripFetchQueryParameterOtherUsage() throws Exception {
+ mHelper.addCustomFilter(
+ String.format("%s#$#strip-fetch-query-parameter otherAllowed2 other-domain",
+ TestPagesHelperBase.TESTPAGES_DOMAIN));
+ mHelper.loadUrlWaitForContent(TestPagesHelperBase.SNIPPETS_TESTPAGES_TESTCASES_ROOT
+ + "strip-fetch-query-parameter");
+ TestVerificationUtils.verifyDisplayedCount(
+ mHelper, 2, "div#other-target > div[data-expectedresult='pass']");
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTestBase.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTestBase.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTestBase.java
@@ -0,0 +1,56 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import androidx.test.filters.LargeTest;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.chromium.base.test.util.Feature;
+import org.chromium.components.adblock.AdblockContentType;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+public abstract class TestPagesWebsocketTestBase {
+ private TestPagesHelperBase mHelper;
+
+ protected void setUp(TestPagesHelperBase helper) {
+ mHelper = helper;
+ mHelper.addCustomFilter(
+ String.format("$websocket,domain=%s", TestPagesHelperBase.TESTPAGES_DOMAIN));
+ }
+
+ @Test
+ @LargeTest
+ @Feature({"adblock"})
+ public void testVerifyWebsocketFilter() throws Exception {
+ final String wssUrl =
+ String.format("wss://%s/websocket", TestPagesHelperBase.TESTPAGES_DOMAIN);
+ final CountDownLatch countDownLatch =
+ mHelper.setOnAdMatchedExpectations(new HashSet<>(List.of(wssUrl)), null);
+ mHelper.loadUrl(TestPagesHelperBase.FILTER_TESTPAGES_TESTCASES_ROOT + "websocket");
+ // Wait with 10 seconds max timeout
+ countDownLatch.await(10, TimeUnit.SECONDS);
+ Assert.assertEquals(1, mHelper.numBlockedByType(AdblockContentType.CONTENT_TYPE_WEBSOCKET));
+ Assert.assertTrue(mHelper.isBlocked(wssUrl));
+ }
+}
diff --git a/components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/javatests/src/org/chromium/components/adblock/TestVerificationUtils.java
@@ -0,0 +1,163 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.chromium.components.adblock;
+
+import org.junit.Assert;
+
+import org.chromium.content_public.browser.test.util.JavaScriptUtils;
+
+import java.util.Locale;
+import java.util.concurrent.TimeoutException;
+
+public class TestVerificationUtils {
+ public enum IncludeSubframes {
+ YES,
+ NO,
+ }
+
+ private static final String STATUS_OK = "\"OK\"";
+
+ private static final String MATCHES_HIDDEN_FUNCTION = "let matches = function(element) {"
+ + " return window.getComputedStyle(element).display == \"none\";"
+ + "}";
+
+ private static final String MATCHES_DISPLAYED_FUNCTION = "let matches = function(element) {"
+ + " return window.getComputedStyle(element).display != \"none\";"
+ + "}";
+
+ private static final String COUNT_ELEMENT_FUNCTION =
+ "let countElements = function(selector, includeSubframes) {"
+ + " let count = 0;"
+ + " for (let element of document.querySelectorAll(selector)) {"
+ + " if (matches(element))"
+ + " ++count;"
+ + " }"
+ + " if (includeSubframes) {"
+ + " for (let frame of document.querySelectorAll(\"iframe\")) {"
+ + " for (let element of frame.contentWindow.document.body"
+ + ".querySelectorAll(selector)) {"
+ + " if (matches(element))"
+ + " ++count;"
+ + " }"
+ + " }"
+ + " }"
+ + " return count;"
+ + "}";
+
+ private static final String WAIT_FOR_COUNT_FUNCTION_WRAPPER = "(function () {"
+ + "%s\n" // matches() definition placeholder
+ + "%s\n" // countElements() definition placeholder
+ + "%s\n" // WAIT_FUNCTION placeholder which calls countElements() as a predicate
+ + "}());";
+
+ // Poll every 100 ms until condition is met or 4 seconds timeout occurs
+ // Internal timeout of JavaScriptUtils.runJavascriptWithAsyncResult() is 5 seconds
+ // so our wait timeout needs to be shorter.
+ private static final String WAIT_FUNCTION = "function waitWithTimeout() {"
+ + " return new Promise(resolve => {"
+ + " let repeat = 40;"
+ + " const id = setInterval(() => {"
+ + " --repeat;"
+ + " if (%s) {" // predicate placeholder
+ + " clearInterval(id);"
+ + " resolve('OK');"
+ + " } else if (repeat == 0) {"
+ + " clearInterval(id);"
+ + " resolve('Timeout');"
+ + " }"
+ + " }, 100);"
+ + " });"
+ + "};"
+ + "waitWithTimeout().then((result) => { domAutomationController.send(result); });";
+
+ private static void verifyMatchesCount(final TestPagesHelperBase helper, final int num,
+ final String matchesFunction, final String selector, IncludeSubframes includeSubframes)
+ throws TimeoutException {
+ final String boolIncludeSubframes =
+ includeSubframes == IncludeSubframes.YES ? "true" : "false";
+ final String predicate = String.format(Locale.getDefault(),
+ "countElements(\"%s\", %s) == %d", selector, boolIncludeSubframes, num);
+ final String waitFunction = String.format(WAIT_FUNCTION, predicate);
+ final String js = String.format(WAIT_FOR_COUNT_FUNCTION_WRAPPER, matchesFunction,
+ COUNT_ELEMENT_FUNCTION, waitFunction);
+ final String result =
+ JavaScriptUtils.runJavascriptWithAsyncResult(helper.getWebContents(), js);
+ Assert.assertEquals(STATUS_OK, result);
+ }
+
+ public static void verifyHiddenCount(final TestPagesHelperBase helper, final int num,
+ final String selector) throws TimeoutException {
+ verifyHiddenCount(helper, num, selector, IncludeSubframes.YES);
+ }
+
+ public static void verifyHiddenCount(final TestPagesHelperBase helper, final int num,
+ final String selector, final IncludeSubframes includeSubframes)
+ throws TimeoutException {
+ verifyMatchesCount(helper, num, MATCHES_HIDDEN_FUNCTION, selector, includeSubframes);
+ }
+
+ public static void verifyDisplayedCount(final TestPagesHelperBase helper, final int num,
+ final String selector) throws TimeoutException {
+ verifyDisplayedCount(helper, num, selector, IncludeSubframes.YES);
+ }
+
+ public static void verifyDisplayedCount(final TestPagesHelperBase helper, final int num,
+ final String selector, final IncludeSubframes includeSubframes)
+ throws TimeoutException {
+ verifyMatchesCount(helper, num, MATCHES_DISPLAYED_FUNCTION, selector, includeSubframes);
+ }
+
+ public static void verifyCondition(final TestPagesHelperBase helper, final String predicate)
+ throws TimeoutException {
+ final String waitFunction = String.format(WAIT_FUNCTION, predicate);
+ Assert.assertEquals(STATUS_OK,
+ JavaScriptUtils.runJavascriptWithAsyncResult(
+ helper.getWebContents(), waitFunction));
+ }
+
+ public static void verifyGreenBackground(final TestPagesHelperBase helper, final String elemId)
+ throws TimeoutException {
+ verifyCondition(helper,
+ "window.getComputedStyle(document.getElementById('" + elemId
+ + "')).backgroundColor == 'rgb(13, 199, 75)'");
+ }
+
+ // For some cases it is better to rely on page script testing element
+ // rather than invent a specific script to check condition. For example
+ // checks for rewrite filters replaces content proper way.
+ public static void verifySelfTestPass(final TestPagesHelperBase helper, final String elemId)
+ throws TimeoutException {
+ verifyCondition(helper,
+ "document.getElementById('" + elemId
+ + "').getAttribute('data-expectedresult') == 'pass'");
+ }
+
+ public static void expectResourceBlocked(final TestPagesHelperBase helper, final String elemId)
+ throws TimeoutException {
+ verifyCondition(helper,
+ "window.getComputedStyle(document.getElementById('" + elemId
+ + "')).display == 'none'");
+ }
+
+ public static void expectResourceShown(final TestPagesHelperBase helper, final String elemId)
+ throws TimeoutException {
+ verifyCondition(helper,
+ "window.getComputedStyle(document.getElementById('" + elemId
+ + "')).display == 'inline'");
+ }
+}
diff --git a/components/adblock/android/resource_classification_notifier_bindings.cc b/components/adblock/android/resource_classification_notifier_bindings.cc
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/resource_classification_notifier_bindings.cc
@@ -0,0 +1,164 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "components/adblock/android/resource_classification_notifier_bindings.h"
+
+#include <iterator>
+#include <memory>
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/ranges/algorithm.h"
+#include "components/adblock/android/java_bindings_getters.h"
+#include "components/adblock/android/jni_headers/ResourceClassificationNotifier_jni.h"
+#include "components/adblock/content/browser/resource_classification_runner.h"
+#include "components/adblock/core/common/adblock_utils.h"
+
+namespace adblock {
+
+using base::android::AttachCurrentThread;
+using base::android::CheckException;
+using base::android::ConvertJavaStringToUTF8;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::GetClass;
+using base::android::JavaParamRef;
+using base::android::JavaRef;
+using base::android::MethodID;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+using base::android::ToJavaArrayOfObjects;
+using base::android::ToJavaArrayOfStrings;
+
+ResourceClassificationNotifierBindings::ResourceClassificationNotifierBindings(
+ ResourceClassificationRunner* classification_runner)
+ : classification_runner_(classification_runner) {
+ classification_runner_->AddObserver(this);
+}
+
+ResourceClassificationNotifierBindings::
+ ~ResourceClassificationNotifierBindings() {
+ classification_runner_->RemoveObserver(this);
+}
+
+void ResourceClassificationNotifierBindings::Bind(
+ JavaObjectWeakGlobalRef resource_classifier_java) {
+ bound_counterpart_ = resource_classifier_java;
+}
+
+void ResourceClassificationNotifierBindings::OnAdMatched(
+ const GURL& url,
+ FilterMatchResult result,
+ const std::vector<GURL>& parent_frame_urls,
+ ContentType content_type,
+ content::RenderFrameHost* render_frame_host,
+ const GURL& subscription,
+ const std::string& configuration_name) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(render_frame_host);
+ DCHECK(result == FilterMatchResult::kBlockRule ||
+ result == FilterMatchResult::kAllowRule);
+ const bool was_blocked = result == FilterMatchResult::kBlockRule;
+ DVLOG(3) << "[eyeo] Ad matched " << url << "(type: " << content_type
+ << (was_blocked ? ", blocked" : ", allowed") << ")";
+ JNIEnv* env = AttachCurrentThread();
+
+ ScopedJavaLocalRef<jobject> obj = bound_counterpart_.get(env);
+ if (obj.is_null()) {
+ return;
+ }
+
+ ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
+ ScopedJavaLocalRef<jobjectArray> j_parents =
+ ToJavaArrayOfStrings(env, adblock::utils::ConvertURLs(parent_frame_urls));
+ ScopedJavaLocalRef<jstring> j_subscription =
+ ConvertUTF8ToJavaString(env, subscription.spec());
+ ScopedJavaLocalRef<jstring> j_configuration =
+ ConvertUTF8ToJavaString(env, configuration_name);
+ int tab_id = adblock::GetTabId(render_frame_host);
+ Java_ResourceClassificationNotifier_adMatchedCallback(
+ env, obj, j_url, was_blocked, j_parents, j_subscription, j_configuration,
+ static_cast<int>(content_type), tab_id);
+}
+
+void ResourceClassificationNotifierBindings::OnPageAllowed(
+ const GURL& url,
+ content::RenderFrameHost* render_frame_host,
+ const GURL& subscription,
+ const std::string& configuration_name) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(render_frame_host);
+ DVLOG(3) << "[eyeo] Page allowed " << url;
+ JNIEnv* env = AttachCurrentThread();
+
+ ScopedJavaLocalRef<jobject> obj = bound_counterpart_.get(env);
+ if (obj.is_null()) {
+ return;
+ }
+
+ ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
+ ScopedJavaLocalRef<jstring> j_subscription =
+ ConvertUTF8ToJavaString(env, subscription.spec());
+ ScopedJavaLocalRef<jstring> j_configuration =
+ ConvertUTF8ToJavaString(env, configuration_name);
+ int tab_id = adblock::GetTabId(render_frame_host);
+ Java_ResourceClassificationNotifier_pageAllowedCallback(
+ env, obj, j_url, j_subscription, j_configuration, tab_id);
+}
+
+void ResourceClassificationNotifierBindings::OnPopupMatched(
+ const GURL& url,
+ FilterMatchResult result,
+ const GURL& opener_url,
+ content::RenderFrameHost* render_frame_host,
+ const GURL& subscription,
+ const std::string& configuration_name) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(render_frame_host);
+ DCHECK(result == FilterMatchResult::kBlockRule ||
+ result == FilterMatchResult::kAllowRule);
+ const bool was_blocked = result == FilterMatchResult::kBlockRule;
+ DVLOG(3) << "[eyeo] Popup matched " << url
+ << (was_blocked ? ", blocked" : ", allowed");
+ JNIEnv* env = AttachCurrentThread();
+
+ ScopedJavaLocalRef<jobject> obj = bound_counterpart_.get(env);
+ if (obj.is_null()) {
+ return;
+ }
+
+ ScopedJavaLocalRef<jstring> j_url = ConvertUTF8ToJavaString(env, url.spec());
+ ScopedJavaLocalRef<jstring> j_opener =
+ ConvertUTF8ToJavaString(env, opener_url.spec());
+ ScopedJavaLocalRef<jstring> j_subscription =
+ ConvertUTF8ToJavaString(env, subscription.spec());
+ ScopedJavaLocalRef<jstring> j_configuration =
+ ConvertUTF8ToJavaString(env, configuration_name);
+ int tab_id = adblock::GetTabId(render_frame_host);
+ Java_ResourceClassificationNotifier_popupMatchedCallback(
+ env, obj, j_url, was_blocked, j_opener, j_subscription, j_configuration,
+ tab_id);
+}
+
+} // namespace adblock
+
+static void JNI_ResourceClassificationNotifier_Bind(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& caller) {
+ auto& bindings = adblock::GetResourceClassificationNotifierBindings();
+ bindings.Bind(JavaObjectWeakGlobalRef(env, caller));
+}
diff --git a/components/adblock/android/resource_classification_notifier_bindings.h b/components/adblock/android/resource_classification_notifier_bindings.h
new file mode 100644
--- /dev/null
+++ b/components/adblock/android/resource_classification_notifier_bindings.h
@@ -0,0 +1,69 @@
+/*
+ * This file is part of eyeo Chromium SDK,
+ * Copyright (C) 2006-present eyeo GmbH
+ *
+ * eyeo Chromium SDK is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 as
+ * published by the Free Software Foundation.
+ *
+ * eyeo Chromium SDK is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef COMPONENTS_ADBLOCK_ANDROID_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_H_
+#define COMPONENTS_ADBLOCK_ANDROID_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_H_
+
+#include <utility>
+#include <vector>
+#include "base/android/jni_weak_ref.h"
+#include "base/memory/raw_ptr.h"
+#include "base/sequence_checker.h"
+#include "components/adblock/content/browser/resource_classification_runner.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "components/prefs/pref_service.h"
+
+namespace adblock {
+
+class ResourceClassificationNotifierBindings
+ : public KeyedService,
+ public ResourceClassificationRunner::Observer {
+ public:
+ explicit ResourceClassificationNotifierBindings(
+ ResourceClassificationRunner* classification_runner);
+ ~ResourceClassificationNotifierBindings() override;
+
+ void Bind(JavaObjectWeakGlobalRef resource_classifier_java);
+
+ // ResourceClassificationRunner::Observer
+ void OnAdMatched(const GURL& url,
+ FilterMatchResult match_result,
+ const std::vector<GURL>& parent_frame_urls,
+ ContentType content_type,
+ content::RenderFrameHost* render_frame_host,
+ const GURL& subscription,
+ const std::string& configuration_name) override;
+ void OnPageAllowed(const GURL& url,
+ content::RenderFrameHost* render_frame_host,
+ const GURL& subscription,
+ const std::string& configuration_name) override;
+ void OnPopupMatched(const GURL& url,
+ FilterMatchResult match_result,
+ const GURL& opener_url,
+ content::RenderFrameHost* render_frame_host,
+ const GURL& subscription,
+ const std::string& configuration_name) override;
+
+ private:
+ SEQUENCE_CHECKER(sequence_checker_);
+ raw_ptr<ResourceClassificationRunner> classification_runner_;
+ JavaObjectWeakGlobalRef bound_counterpart_;
+};
+
+} // namespace adblock
+
+#endif // COMPONENTS_ADBLOCK_ANDROID_RESOURCE_CLASSIFICATION_NOTIFIER_BINDINGS_H_
--
2.25.1