diff --git a/build/bromite_patches_list.txt b/build/bromite_patches_list.txt index a763c950..057f5644 100644 --- a/build/bromite_patches_list.txt +++ b/build/bromite_patches_list.txt @@ -207,3 +207,6 @@ Remove-http-referrals-in-cross-origin-navigation.patch 00Experimental-user-scripts-support--fixup-.patch 00Remove-navigator-connection-info--fixup-.patch +00Experimental-user-scripts-support--fixup--2.patch +00Eyeo-Adblock.patch +00Eyeo-Adblock-Remove-Privacy-Issues.patch \ No newline at end of file diff --git a/build/patches/00Experimental-user-scripts-support--fixup--2.patch b/build/patches/00Experimental-user-scripts-support--fixup--2.patch new file mode 100644 index 00000000..cb9035f2 --- /dev/null +++ b/build/patches/00Experimental-user-scripts-support--fixup--2.patch @@ -0,0 +1,84 @@ +From: Your Name +Date: Wed, 28 Sep 2022 12:49:17 +0000 +Subject: Experimental user scripts support (fixup) 2 + +--- + .../user_scripts/renderer/script_context.cc | 26 +------------------ + .../user_scripts/renderer/user_script_set.cc | 12 ++++++--- + 2 files changed, 9 insertions(+), 29 deletions(-) + +diff --git a/components/user_scripts/renderer/script_context.cc b/components/user_scripts/renderer/script_context.cc +--- a/components/user_scripts/renderer/script_context.cc ++++ b/components/user_scripts/renderer/script_context.cc +@@ -167,36 +167,12 @@ GURL GetEffectiveDocumentURL( + return parent_url; + } + +-using FrameToDocumentLoader = +- base::flat_map; +- +-FrameToDocumentLoader& FrameDocumentLoaderMap() { +- static base::NoDestructor map; +- return *map; +-} +- +-blink::WebDocumentLoader* CurrentDocumentLoader( +- const blink::WebLocalFrame* frame) { +- auto& map = FrameDocumentLoaderMap(); +- auto it = map.find(frame); +- return it == map.end() ? frame->GetDocumentLoader() : it->second; +-} +- + } // namespace + + // static + GURL ScriptContext::GetDocumentLoaderURLForFrame( + const blink::WebLocalFrame* frame) { +- // Normally we would use frame->document().url() to determine the document's +- // URL, but to decide whether to inject a content script, we use the URL from +- // the data source. This "quirk" helps prevents content scripts from +- // inadvertently adding DOM elements to the compose iframe in Gmail because +- // the compose iframe's dataSource URL is about:blank, but the document URL +- // changes to match the parent document after Gmail document.writes into +- // it to create the editor. +- // http://code.google.com/p/chromium/issues/detail?id=86742 +- blink::WebDocumentLoader* document_loader = CurrentDocumentLoader(frame); +- return document_loader ? GURL(document_loader->GetUrl()) : GURL(); ++ return GURL(frame->GetDocument().Url()); + } + + // static +diff --git a/components/user_scripts/renderer/user_script_set.cc b/components/user_scripts/renderer/user_script_set.cc +--- a/components/user_scripts/renderer/user_script_set.cc ++++ b/components/user_scripts/renderer/user_script_set.cc +@@ -218,6 +218,14 @@ std::unique_ptr UserScriptSet::GetInjectionForScript( + + blink::WebString UserScriptSet::GetJsSource(const UserScript::File& file, + bool emulate_greasemonkey) { ++ if (base::FeatureList::IsEnabled(features::kEnableLoggingUserScripts)) { ++ if (emulate_greasemonkey) { ++ LOG(INFO) << "UserScripts: Injecting w/greasemonkey " << file.url(); ++ } else { ++ LOG(INFO) << "UserScripts: Injecting " << file.url(); ++ } ++ } ++ + const GURL& url = file.url(); + auto iter = script_sources_.find(url); + if (iter != script_sources_.end()) { +@@ -233,13 +241,9 @@ blink::WebString UserScriptSet::GetJsSource(const UserScript::File& file, + std::string content = + base::StrCat({kUserScriptHead, script_content, kUserScriptTail}); + source = blink::WebString::FromUTF8(content); +- if (base::FeatureList::IsEnabled(features::kEnableLoggingUserScripts)) +- LOG(INFO) << "UserScripts: Injecting w/greasemonkey " << file.url(); + } else { + source = blink::WebString::FromUTF8(script_content.data(), + script_content.length()); +- if (base::FeatureList::IsEnabled(features::kEnableLoggingUserScripts)) +- LOG(INFO) << "UserScripts: Injecting " << file.url(); + } + script_sources_[url] = source; + return source; +-- +2.25.1 diff --git a/build/patches/00Eyeo-Adblock-Remove-Privacy-Issues.patch b/build/patches/00Eyeo-Adblock-Remove-Privacy-Issues.patch new file mode 100644 index 00000000..c06bac08 --- /dev/null +++ b/build/patches/00Eyeo-Adblock-Remove-Privacy-Issues.patch @@ -0,0 +1,5392 @@ +From: Your Name +Date: Thu, 29 Sep 2022 11:27:35 +0000 +Subject: Eyeo Adblock Remove + +--- + .../android/java/res/xml/main_preferences.xml | 2 +- + chrome/browser/BUILD.gn | 3 - + .../adblock/adblock_content_browser_client.cc | 26 - + .../adblock_telemetry_service_factory.cc | 91 - + .../adblock_telemetry_service_factory.h | 50 - + .../adblock/subscription_updater_factory.cc | 2 +- + ...hrome_browser_main_extra_parts_profiles.cc | 2 - + components/adblock/android/BUILD.gn | 2 +- + .../layout/adblock_filter_lists_list_item.xml | 10 + + ...ences.xml => eyeo_adblock_preferences.xml} | 0 + .../settings/AdblockFilterListsAdapter.java | 3 + + .../settings/AdblockSettingsFragment.java | 2 +- + components/adblock/content/BUILD.gn | 2 - + components/adblock/content/common/BUILD.gn | 7 - + .../common/adblock_url_loader_factory.cc | 22 +- + .../adblock_url_loader_factory_for_test.cc | 196 -- + .../adblock_url_loader_factory_for_test.h | 73 - + components/adblock/core/BUILD.gn | 74 - + .../activeping_telemetry_topic_provider.cc | 206 -- + .../activeping_telemetry_topic_provider.h | 72 - + .../adblock/core/adblock_controller_impl.cc | 8 +- + .../adblock/core/adblock_telemetry_service.cc | 216 -- + .../adblock/core/adblock_telemetry_service.h | 96 - + .../adblock/core/common/adblock_constants.cc | 2 - + .../adblock/core/common/adblock_constants.h | 1 - + .../adblock/core/common/adblock_prefs.cc | 42 +- + .../adblock/core/common/adblock_utils.cc | 23 - + components/adblock/core/converter/metadata.cc | 6 +- + components/adblock/core/features.gni | 46 - + .../adblock/core/sitekey_storage_impl.cc | 6 + + .../ongoing_subscription_request_impl.cc | 15 +- + .../preloaded_subscription_provider_impl.cc | 4 +- + .../core/subscription/subscription_config.cc | 8 +- + .../subscription_downloader_impl.cc | 15 +- + .../subscription_persistent_storage_impl.cc | 4 + + .../core/subscription/subscription_service.h | 4 - + .../subscription/subscription_service_impl.cc | 15 +- + .../subscription/subscription_service_impl.h | 1 - + .../subscription/subscription_updater_impl.cc | 27 +- + .../subscription_validator_impl.cc | 8 +- + components/resources/BUILD.gn | 1 - + components/resources/adblock_resources.grdp | 3 - + components/resources/adblocking/.gitignore | 2 +- + components/resources/adblocking/BUILD.gn | 25 +- + .../snippets/dist/isolated-first.jst | 62 + + .../snippets/dist/isolated-first.source.jst | 3126 +++++++++++++++++ + 46 files changed, 3271 insertions(+), 1340 deletions(-) + delete mode 100644 chrome/browser/adblock/adblock_telemetry_service_factory.cc + delete mode 100644 chrome/browser/adblock/adblock_telemetry_service_factory.h + rename components/adblock/android/java/res/xml/{adblock_preferences.xml => eyeo_adblock_preferences.xml} (100%) + delete mode 100644 components/adblock/content/common/adblock_url_loader_factory_for_test.cc + delete mode 100644 components/adblock/content/common/adblock_url_loader_factory_for_test.h + delete mode 100644 components/adblock/core/activeping_telemetry_topic_provider.cc + delete mode 100644 components/adblock/core/activeping_telemetry_topic_provider.h + delete mode 100644 components/adblock/core/adblock_telemetry_service.cc + delete mode 100644 components/adblock/core/adblock_telemetry_service.h + delete mode 100644 components/adblock/core/features.gni + create mode 100755 components/resources/adblocking/snippets/dist/isolated-first.jst + create mode 100755 components/resources/adblocking/snippets/dist/isolated-first.source.jst + +diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml +--- a/chrome/android/java/res/xml/main_preferences.xml ++++ b/chrome/android/java/res/xml/main_preferences.xml +@@ -82,7 +82,7 @@ + android:title="@string/prefs_accessibility"/> + + SetUserData(kAdblockContextUserDataKey, base::WrapUnique(self)); + } +-#ifndef NDEBUG +- content::WebContents* wc = content::WebContents::FromRenderFrameHost(frame); +- bool is_adblock_test_url = +- (type == +- content::ContentBrowserClient::URLLoaderFactoryType::kNavigation) && +- wc->GetVisibleURL().is_valid() && +- wc->GetVisibleURL().host() == +- adblock::AdblockURLLoaderFactoryForTest::kAdblockDebugDataHostName; +- if (is_adblock_test_url) { +- auto proxy = std::make_unique( +- std::make_unique( +- render_process_id), +- frame->GetRoutingID(), std::move(receiver), std::move(target_factory), +- embedder_support::GetUserAgent(), +- base::BindOnce(&AdblockContextData::RemoveProxy, +- self->weak_factory_.GetWeakPtr()), +- adblock::AdblockControllerFactory::GetForBrowserContext( +- Profile::FromBrowserContext( +- frame->GetProcess()->GetBrowserContext()))); +- self->proxies_.emplace(std::move(proxy)); +- return; +- } +-#endif + auto proxy = std::make_unique( + std::make_unique(render_process_id), + frame->GetRoutingID(), std::move(receiver), std::move(target_factory), +diff --git a/chrome/browser/adblock/adblock_telemetry_service_factory.cc b/chrome/browser/adblock/adblock_telemetry_service_factory.cc +deleted file mode 100644 +--- a/chrome/browser/adblock/adblock_telemetry_service_factory.cc ++++ /dev/null +@@ -1,91 +0,0 @@ +-/* +- * 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 . +- */ +- +-#include "chrome/browser/adblock/adblock_telemetry_service_factory.h" +- +-#include +- +-#include "base/no_destructor.h" +-#include "chrome/browser/profiles/incognito_helpers.h" +-#include "chrome/browser/profiles/profile.h" +-#include "chrome/common/pref_names.h" +-#include "components/adblock/core/activeping_telemetry_topic_provider.h" +-#include "components/adblock/core/adblock_telemetry_service.h" +-#include "components/adblock/core/common/adblock_utils.h" +-#include "components/keyed_service/content/browser_context_dependency_manager.h" +-#include "content/public/browser/storage_partition.h" +- +-namespace adblock { +- +-// static +-AdblockTelemetryService* AdblockTelemetryServiceFactory::GetForProfile( +- Profile* profile) { +- return static_cast( +- GetInstance()->GetServiceForBrowserContext(profile, true)); +-} +-// static +-AdblockTelemetryServiceFactory* AdblockTelemetryServiceFactory::GetInstance() { +- static base::NoDestructor instance; +- return instance.get(); +-} +- +-AdblockTelemetryServiceFactory::AdblockTelemetryServiceFactory() +- : BrowserContextKeyedServiceFactory( +- "AdblockTelemetryService", +- BrowserContextDependencyManager::GetInstance()) {} +- +-AdblockTelemetryServiceFactory::~AdblockTelemetryServiceFactory() = default; +- +-KeyedService* AdblockTelemetryServiceFactory::BuildServiceInstanceFor( +- content::BrowserContext* context) const { +- // Need to use a URLLoaderFactory specific to the browser context, not from +- // system_network_context_manager(), because the required Accept-Language +- // header depends on user's language settings and is not present in requests +- // made from the System network context. +- scoped_refptr url_loader_factory = +- context->GetDefaultStoragePartition() +- ->GetURLLoaderFactoryForBrowserProcess(); +- auto* prefs = Profile::FromBrowserContext(context)->GetPrefs(); +- auto service = +- std::make_unique(prefs, url_loader_factory); +- +- service->AddTopicProvider(std::make_unique( +- utils::GetAppInfo(), prefs, +- ActivepingTelemetryTopicProvider::DefaultBaseUrl(), +- ActivepingTelemetryTopicProvider::DefaultAuthToken())); +- +- if (url_loader_factory) +- service->Start(); +- +- return service.release(); +-} +- +-content::BrowserContext* AdblockTelemetryServiceFactory::GetBrowserContextToUse( +- content::BrowserContext* context) const { +- return chrome::GetBrowserContextRedirectedInIncognito(context); +-} +- +-bool AdblockTelemetryServiceFactory::ServiceIsNULLWhileTesting() const { +- return true; +-} +- +-bool AdblockTelemetryServiceFactory::ServiceIsCreatedWithBrowserContext() +- const { +- return true; +-} +- +-} // namespace adblock +diff --git a/chrome/browser/adblock/adblock_telemetry_service_factory.h b/chrome/browser/adblock/adblock_telemetry_service_factory.h +deleted file mode 100644 +--- a/chrome/browser/adblock/adblock_telemetry_service_factory.h ++++ /dev/null +@@ -1,50 +0,0 @@ +-/* +- * 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 . +- */ +- +-#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ +-#define CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ +- +-#include "base/no_destructor.h" +-#include "components/keyed_service/content/browser_context_keyed_service_factory.h" +- +-class Profile; +- +-namespace adblock { +-class AdblockTelemetryService; +-class AdblockTelemetryServiceFactory +- : public BrowserContextKeyedServiceFactory { +- public: +- static AdblockTelemetryService* GetForProfile(Profile* profile); +- static AdblockTelemetryServiceFactory* GetInstance(); +- +- private: +- friend class base::NoDestructor; +- AdblockTelemetryServiceFactory(); +- ~AdblockTelemetryServiceFactory() override; +- +- // BrowserContextKeyedServiceFactory: +- KeyedService* BuildServiceInstanceFor( +- content::BrowserContext* context) const override; +- content::BrowserContext* GetBrowserContextToUse( +- content::BrowserContext* context) const override; +- bool ServiceIsNULLWhileTesting() const override; +- bool ServiceIsCreatedWithBrowserContext() const override; +-}; +- +-} // namespace adblock +- +-#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ +diff --git a/chrome/browser/adblock/subscription_updater_factory.cc b/chrome/browser/adblock/subscription_updater_factory.cc +--- a/chrome/browser/adblock/subscription_updater_factory.cc ++++ b/chrome/browser/adblock/subscription_updater_factory.cc +@@ -30,7 +30,7 @@ + namespace adblock { + namespace { + constexpr auto kInitialDelay = base::Seconds(30); +-constexpr auto kCheckInterval = base::Hours(1); ++constexpr auto kCheckInterval = base::Hours(24); + } // namespace + + // static +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 +@@ -16,7 +16,6 @@ + #include "chrome/browser/accessibility/page_colors_factory.h" + #include "chrome/browser/accuracy_tips/accuracy_service_factory.h" + #include "chrome/browser/adblock/adblock_controller_factory.h" +-#include "chrome/browser/adblock/adblock_telemetry_service_factory.h" + #include "chrome/browser/adblock/resource_classification_runner_factory.h" + #include "chrome/browser/adblock/session_stats_factory.h" + #include "chrome/browser/adblock/sitekey_storage_factory.h" +@@ -391,7 +390,6 @@ void ChromeBrowserMainExtraPartsProfiles:: + ExitTypeServiceFactory::GetInstance(); + #endif + adblock::AdblockControllerFactory::GetInstance(); +- adblock::AdblockTelemetryServiceFactory::GetInstance(); + adblock::ResourceClassificationRunnerFactory::GetInstance(); + adblock::SessionStatsFactory::GetInstance(); + adblock::SitekeyStorageFactory::GetInstance(); +diff --git a/components/adblock/android/BUILD.gn b/components/adblock/android/BUILD.gn +--- a/components/adblock/android/BUILD.gn ++++ b/components/adblock/android/BUILD.gn +@@ -83,7 +83,7 @@ android_resources("java_resources") { + "java/res/layout/adblock_filter_lists_list_item.xml", + "java/res/values/adblock_settings_locales_titles.xml", + "java/res/xml/adblock_more_options.xml", +- "java/res/xml/adblock_preferences.xml", ++ "java/res/xml/eyeo_adblock_preferences.xml", + ] + + deps = [ ":adblock_strings_grd" ] +diff --git a/components/adblock/android/java/res/layout/adblock_filter_lists_list_item.xml b/components/adblock/android/java/res/layout/adblock_filter_lists_list_item.xml +--- a/components/adblock/android/java/res/layout/adblock_filter_lists_list_item.xml ++++ b/components/adblock/android/java/res/layout/adblock_filter_lists_list_item.xml +@@ -28,9 +28,19 @@ + android:layout_height="wrap_content" + android:layout_marginEnd="21dp" + android:clickable="false" /> ++ + ++ ++ + +diff --git a/components/adblock/android/java/res/xml/adblock_preferences.xml b/components/adblock/android/java/res/xml/eyeo_adblock_preferences.xml +similarity index 100% +rename from components/adblock/android/java/res/xml/adblock_preferences.xml +rename to components/adblock/android/java/res/xml/eyeo_adblock_preferences.xml +diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockFilterListsAdapter.java b/components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockFilterListsAdapter.java +--- a/components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockFilterListsAdapter.java ++++ b/components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockFilterListsAdapter.java +@@ -93,6 +93,9 @@ public class AdblockFilterListsAdapter extends BaseAdapter implements OnClickLis + TextView description = view.findViewById(R.id.name); + description.setText(item.title()); + description.setContentDescription(item.title() + "filer list item title text"); ++ ++ TextView url = view.findViewById(R.id.url); ++ url.setText(item.url().toString()); + return view; + } + +diff --git a/components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockSettingsFragment.java b/components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockSettingsFragment.java +--- a/components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockSettingsFragment.java ++++ b/components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockSettingsFragment.java +@@ -114,7 +114,7 @@ public class AdblockSettingsFragment + + @Override + public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { +- addPreferencesFromResource(R.xml.adblock_preferences); ++ addPreferencesFromResource(R.xml.eyeo_adblock_preferences); + bindPreferences(); + synchronizePreferences(); + } +diff --git a/components/adblock/content/BUILD.gn b/components/adblock/content/BUILD.gn +--- a/components/adblock/content/BUILD.gn ++++ b/components/adblock/content/BUILD.gn +@@ -16,8 +16,6 @@ + + assert(!is_ios) + +-import("//components/adblock/core/features.gni") +- + # External targets should depend on this + group("browser") { + public_deps = [ "//components/adblock/content/browser:browser_impl" ] +diff --git a/components/adblock/content/common/BUILD.gn b/components/adblock/content/common/BUILD.gn +--- a/components/adblock/content/common/BUILD.gn ++++ b/components/adblock/content/common/BUILD.gn +@@ -24,13 +24,6 @@ source_set("common_impl") { + "adblock_url_loader_factory.h", + ] + +- if (is_debug) { +- sources += [ +- "adblock_url_loader_factory_for_test.cc", +- "adblock_url_loader_factory_for_test.h", +- ] +- } +- + deps = [ + "//components/adblock/core", + "//third_party/blink/public/common:headers", +diff --git a/components/adblock/content/common/adblock_url_loader_factory.cc b/components/adblock/content/common/adblock_url_loader_factory.cc +--- a/components/adblock/content/common/adblock_url_loader_factory.cc ++++ b/components/adblock/content/common/adblock_url_loader_factory.cc +@@ -60,13 +60,13 @@ class AdblockURLLoaderFactory::InProgressRequest + ::network::mojom::EarlyHintsPtr early_hints) override; + void OnReceiveResponse( + ::network::mojom::URLResponseHeadPtr head, +- ::mojo::ScopedDataPipeConsumerHandle body, +- absl::optional cached_metadata) override; ++ ::mojo::ScopedDataPipeConsumerHandle body) override; + void OnReceiveRedirect(const ::net::RedirectInfo& redirect_info, + ::network::mojom::URLResponseHeadPtr head) override; + void OnUploadProgress(int64_t current_position, + int64_t total_size, + OnUploadProgressCallback callback) override; ++ void OnReceiveCachedMetadata(::mojo_base::BigBuffer data) override; + void OnTransferSizeUpdated(int32_t transfer_size_diff) override; + void OnComplete(const ::network::URLLoaderCompletionStatus& status) override; + +@@ -91,7 +91,6 @@ class AdblockURLLoaderFactory::InProgressRequest + void OnProcessHeadersResult( + ::network::mojom::URLResponseHeadPtr head, + ::mojo::ScopedDataPipeConsumerHandle body, +- absl::optional cached_metadata, + adblock::mojom::FilterMatchResult result, + network::mojom::ParsedHeadersPtr parsed_headers); + void OnRequestError(int error_code); +@@ -182,15 +181,13 @@ void AdblockURLLoaderFactory::InProgressRequest::OnReceiveEarlyHints( + + void AdblockURLLoaderFactory::InProgressRequest::OnReceiveResponse( + network::mojom::URLResponseHeadPtr head, +- mojo::ScopedDataPipeConsumerHandle body, +- absl::optional cached_metadata) { ++ mojo::ScopedDataPipeConsumerHandle body) { + if (net::IsLocalhost(request_url_) || (!request_url_.SchemeIsHTTPOrHTTPS() && + !request_url_.SchemeIsWSOrWSS())) { + VLOG(1) + << "[eyeo] Ignoring URL (local url or unsupported scheme), allowing " + "load."; +- target_client_->OnReceiveResponse(std::move(head), std::move(body), +- std::move(cached_metadata)); ++ target_client_->OnReceiveResponse(std::move(head), std::move(body)); + return; + } + +@@ -201,13 +198,12 @@ void AdblockURLLoaderFactory::InProgressRequest::OnReceiveResponse( + request_url_, factory_->frame_tree_node_id_, headers, user_agent_string_, + base::BindOnce(&InProgressRequest::OnProcessHeadersResult, + weak_factory_.GetWeakPtr(), std::move(head), +- std::move(body), std::move(cached_metadata))); ++ std::move(body))); + } + + void AdblockURLLoaderFactory::InProgressRequest::OnProcessHeadersResult( + ::network::mojom::URLResponseHeadPtr head, + ::mojo::ScopedDataPipeConsumerHandle body, +- absl::optional cached_metadata, + adblock::mojom::FilterMatchResult result, + network::mojom::ParsedHeadersPtr parsed_headers) { + if (result == adblock::mojom::FilterMatchResult::kBlockRule) { +@@ -222,8 +218,7 @@ void AdblockURLLoaderFactory::InProgressRequest::OnProcessHeadersResult( + head->parsed_headers = std::move(parsed_headers); + } + +- target_client_->OnReceiveResponse(std::move(head), std::move(body), +- std::move(cached_metadata)); ++ target_client_->OnReceiveResponse(std::move(head), std::move(body)); + client_receiver_.Resume(); + } + +@@ -248,6 +243,11 @@ void AdblockURLLoaderFactory::InProgressRequest::OnUploadProgress( + std::move(callback)); + } + ++void AdblockURLLoaderFactory::InProgressRequest::OnReceiveCachedMetadata( ++ mojo_base::BigBuffer data) { ++ target_client_->OnReceiveCachedMetadata(std::move(data)); ++} ++ + void AdblockURLLoaderFactory::InProgressRequest::OnTransferSizeUpdated( + int32_t transfer_size_diff) { + target_client_->OnTransferSizeUpdated(transfer_size_diff); +diff --git a/components/adblock/content/common/adblock_url_loader_factory_for_test.cc b/components/adblock/content/common/adblock_url_loader_factory_for_test.cc +deleted file mode 100644 +--- a/components/adblock/content/common/adblock_url_loader_factory_for_test.cc ++++ /dev/null +@@ -1,196 +0,0 @@ +-/* +- * 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 . +- */ +- +-#include "components/adblock/content/common/adblock_url_loader_factory_for_test.h" +- +-#include "base/strings/string_split.h" +-#include "base/strings/string_util.h" +-#include "base/strings/utf_string_conversions.cc" +-#include "net/http/http_status_code.h" +-#include "net/http/http_util.h" +-#include "services/network/public/cpp/resource_request.h" +-#include "services/network/public/mojom/url_loader.mojom.h" +-#include "services/network/public/mojom/url_loader_factory.mojom.h" +-#include "services/network/public/mojom/url_response_head.mojom.h" +-#include "url/url_canon.h" +-#include "url/url_util.h" +- +-namespace { +- +-std::string DecodePayload(const std::string& encoded) { +- // Example how to encode: +- // url::RawCanonOutputT buffer; +- // url::EncodeURIComponent(base.c_str(), base.size(), &buffer); +- // std::string encoded(buffer.data(), buffer.length()); +- VLOG(2) << "[eyeo] Encoded payload: " << encoded; +- url::RawCanonOutputT output; +- url::DecodeURLEscapeSequences(encoded.c_str(), encoded.size(), +- url::DecodeURLMode::kUTF8OrIsomorphic, &output); +- std::string decoded = +- base::UTF16ToUTF8(std::u16string(output.data(), output.length())); +- VLOG(2) << "[eyeo] Decoded payload: " << decoded; +- return decoded; +-} +- +-std::string GetPayload(const std::string& input) { +- static const char kPayloadParam[] = "payload="; +- if (base::StartsWith(input, kPayloadParam)) { +- return input.substr(sizeof(kPayloadParam) - 1); +- } +- return ""; +-} +- +-void ClearFilters(adblock::AdblockController* adblock_controller) { +- for (auto filter : adblock_controller->GetCustomFilters()) { +- adblock_controller->RemoveCustomFilter(filter); +- } +-} +- +-std::vector ListFilters( +- adblock::AdblockController* adblock_controller) { +- return adblock_controller->GetCustomFilters(); +-} +- +-void AddOrRemoveFilters( +- adblock::AdblockController* adblock_controller, +- void (adblock::AdblockController::*action)(const std::string&), +- std::string& filters) { +- static const char delimiter[] = "\n"; +- auto filters_list = base::SplitString( +- filters, delimiter, base::WhitespaceHandling::TRIM_WHITESPACE, +- base::SplitResult::SPLIT_WANT_NONEMPTY); +- for (auto filter : filters_list) { +- (adblock_controller->*action)(filter); +- } +-} +- +-} // namespace +- +-namespace adblock { +- +-// static +-const std::string AdblockURLLoaderFactoryForTest::kAdblockDebugDataHostName = +- "adblock.test.data"; +- +-AdblockURLLoaderFactoryForTest::AdblockURLLoaderFactoryForTest( +- std::unique_ptr adblock_interface, +- int frame_tree_node_id, +- mojo::PendingReceiver receiver, +- mojo::PendingRemote target_factory, +- std::string user_agent_string, +- DisconnectCallback on_disconnect, +- AdblockController* adblock_controller) +- : AdblockURLLoaderFactory(std::move(adblock_interface), +- frame_tree_node_id, +- std::move(receiver), +- std::move(target_factory), +- user_agent_string, +- std::move(on_disconnect)), +- adblock_controller_(adblock_controller) {} +- +-AdblockURLLoaderFactoryForTest::~AdblockURLLoaderFactoryForTest() = default; +- +-void AdblockURLLoaderFactoryForTest::CreateLoaderAndStart( +- ::mojo::PendingReceiver loader, +- int32_t request_id, +- uint32_t options, +- const network::ResourceRequest& request, +- ::mojo::PendingRemote client, +- const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) { +- DCHECK(adblock_controller_); +- DCHECK(request.url.host() == kAdblockDebugDataHostName); +- VLOG(2) << "[eyeo] AdblockURLLoaderFactoryForTest handles: " << request.url; +- std::string response_body = HandleCommand(request.url); +- SendResponse(std::move(response_body), std::move(client)); +-} +- +-void AdblockURLLoaderFactoryForTest::SendResponse( +- std::string response_body, +- ::mojo::PendingRemote client) const { +- auto response_head = network::mojom::URLResponseHead::New(); +- response_head->mime_type = "text/plain"; +- mojo::Remote client_remote( +- std::move(client)); +- mojo::ScopedDataPipeProducerHandle producer; +- mojo::ScopedDataPipeConsumerHandle consumer; +- if (CreateDataPipe(nullptr, producer, consumer) != MOJO_RESULT_OK) { +- DLOG(ERROR) +- << "[eyeo] AdblockURLLoaderFactoryForTest fails to call CreateDataPipe"; +- client_remote->OnComplete( +- network::URLLoaderCompletionStatus(net::ERR_INSUFFICIENT_RESOURCES)); +- return; +- } +- uint32_t write_size = static_cast(response_body.size()); +- producer->WriteData(response_body.c_str(), &write_size, +- MOJO_WRITE_DATA_FLAG_NONE); +- client_remote->OnReceiveResponse(std::move(response_head), +-// std::move(consumer), absl::nullopt); +-// UAZO +- std::move(consumer)); +- network::URLLoaderCompletionStatus status; +- status.error_code = net::OK; +- status.decoded_body_length = write_size; +- client_remote->OnComplete(status); +-} +- +-std::string AdblockURLLoaderFactoryForTest::HandleCommand( +- const GURL& url) const { +- static const char kResponseOk[] = "OK"; +- static const char kResponseInvalidCommand[] = "INVALID_COMMAND"; +- static const char kResponseInvalidPayload[] = "INVALID_PAYLOAD"; +- static const char kCommandAdd[] = "/add"; +- static const char kCommandClear[] = "/clear"; +- static const char kCommandList[] = "/list"; +- static const char kCommandRemove[] = "/remove"; +- +- std::string command = url.path(); +- if (command == kCommandAdd || command == kCommandRemove) { +- std::string payload = DecodePayload(GetPayload(url.query())); +- if (payload.empty()) { +- return kResponseInvalidPayload; +- } +- if (command == kCommandAdd) { +- VLOG(2) << "[eyeo] Adding filter(s): " << payload; +- AddOrRemoveFilters(adblock_controller_, +- &adblock::AdblockController::AddCustomFilter, payload); +- } else { +- VLOG(2) << "[eyeo] Removing filter(s): " << payload; +- AddOrRemoveFilters(adblock_controller_, +- &adblock::AdblockController::RemoveCustomFilter, +- payload); +- } +- return kResponseOk; +- } else if (command == kCommandClear) { +- VLOG(2) << "[eyeo] Clearing filters"; +- ClearFilters(adblock_controller_); +- return kResponseOk; +- } else if (command == kCommandList) { +- VLOG(2) << "[eyeo] Listing filters"; +- std::vector filters = ListFilters(adblock_controller_); +- std::string response = kResponseOk; +- if (!filters.empty()) { +- response += "\n\n"; +- for (auto filter : filters) { +- response += filter + "\n"; +- } +- } +- return response; +- } +- return kResponseInvalidCommand; +-} +- +-} // namespace adblock +diff --git a/components/adblock/content/common/adblock_url_loader_factory_for_test.h b/components/adblock/content/common/adblock_url_loader_factory_for_test.h +deleted file mode 100644 +--- a/components/adblock/content/common/adblock_url_loader_factory_for_test.h ++++ /dev/null +@@ -1,73 +0,0 @@ +-/* +- * 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 . +- */ +- +-#ifndef COMPONENTS_ADBLOCK_CONTENT_COMMON_ADBLOCK_URL_LOADER_FACTORY_FOR_TEST_H_ +-#define COMPONENTS_ADBLOCK_CONTENT_COMMON_ADBLOCK_URL_LOADER_FACTORY_FOR_TEST_H_ +- +-#include "components/adblock/content/common/adblock_url_loader_factory.h" +-#include "components/adblock/core/adblock_controller.h" +- +-namespace adblock { +- +-// A simple class which handles following commands passed via intercepted url: +-// - add filter, f.e. `adblock.test.data/add?payload=filer_text_to_add` +-// - remove filter, f.e. `adblock.test.data/remove?payload=filer_text_to_remove` +-// - clear all filter, f.e. `adblock.test.data/clear` +-// - list all filter, f.e. ``adblock.test.data/list` +-// `filer_text_to_add` is expected to be an url encoded string. +-// When adding or removing filter one can encode several entries splitting them +-// by a new line character. Real example: +-// - call `adblock.test.data/add?payload=%2FadsPlugin%2F%2A%0A%2Fadsponsor.` +-// - then calling `adblock.test.data/list` returns: +-// OK +-// +-// /adsPlugin/* +-// /adsponsor. +-class AdblockURLLoaderFactoryForTest final : public AdblockURLLoaderFactory { +- public: +- AdblockURLLoaderFactoryForTest( +- std::unique_ptr adblock_interface, +- int frame_tree_node_id, +- mojo::PendingReceiver receiver, +- mojo::PendingRemote target_factory, +- std::string user_agent_string, +- DisconnectCallback on_disconnect, +- AdblockController* adblock_controller); +- ~AdblockURLLoaderFactoryForTest() final; +- +- void CreateLoaderAndStart( +- ::mojo::PendingReceiver<::network::mojom::URLLoader> loader, +- int32_t request_id, +- uint32_t options, +- const ::network::ResourceRequest& request, +- ::mojo::PendingRemote<::network::mojom::URLLoaderClient> client, +- const ::net::MutableNetworkTrafficAnnotationTag& traffic_annotation) +- final; +- +- static const std::string kAdblockDebugDataHostName; +- +- private: +- std::string HandleCommand(const GURL& url) const; +- void SendResponse( +- std::string response_body, +- ::mojo::PendingRemote client) const; +- AdblockController* adblock_controller_; +-}; +- +-} // namespace adblock +- +-#endif // COMPONENTS_ADBLOCK_CONTENT_COMMON_ADBLOCK_URL_LOADER_FACTORY_FOR_TEST_H_ +diff --git a/components/adblock/core/BUILD.gn b/components/adblock/core/BUILD.gn +--- a/components/adblock/core/BUILD.gn ++++ b/components/adblock/core/BUILD.gn +@@ -14,7 +14,6 @@ + # You should have received a copy of the GNU General Public License + # along with eyeo Chromium SDK. If not, see . + +-import("//components/adblock/core/features.gni") + import("//third_party/flatbuffers/flatbuffer.gni") + + flatbuffer("schema") { +@@ -61,81 +60,14 @@ generate_sha256_header("schema_hash") { + files_to_hash = [ "${target_gen_dir}/schema/filter_list_schema_generated.h" ] + } + +-config("adblock_core_config") { +- defines = [] +- +- if (eyeo_telemetry_server_url != "") { +- # Expicitly setting Telemetry server URL, used for testing with a test +- # server. +- defines += [ "EYEO_TELEMETRY_SERVER_URL=\"$eyeo_telemetry_server_url\"" ] +- } else if (abp_telemetry_server_url != "") { +- print("WARNING! abp_telemetry_server_url is deprecated, " + +- "use eyeo_telemetry_server_url instead.") +- eyeo_telemetry_server_url = abp_telemetry_server_url +- defines += [ "EYEO_TELEMETRY_SERVER_URL=\"$eyeo_telemetry_server_url\"" ] +- } else { +- # Implicitly setting production Telemetry server URL based on +- # eyeo_telemetry_client_id (or a default client id as a fallback). +- if (eyeo_telemetry_client_id != "") { +- defines += [ "EYEO_TELEMETRY_CLIENT_ID=\"$eyeo_telemetry_client_id\"" ] +- } else if (abp_telemetry_client_id != "") { +- print("WARNING! abp_telemetry_client_id is deprecated, " + +- "use eyeo_telemetry_client_id instead.") +- eyeo_telemetry_client_id = abp_telemetry_client_id +- defines += [ "EYEO_TELEMETRY_CLIENT_ID=\"$eyeo_telemetry_client_id\"" ] +- } else { +- print("WARNING! gn arg eyeo_telemetry_client_id is not set. " + +- "Users will not be counted correctly by eyeo.") +- eyeo_telemetry_client_id = "eyeochromium" +- } +- eyeo_telemetry_server_url = +- "https://${eyeo_telemetry_client_id}.telemetry.eyeo.com/" +- defines += [ "EYEO_TELEMETRY_SERVER_URL=\"$eyeo_telemetry_server_url\"" ] +- } +- +- if (eyeo_telemetry_activeping_auth_token != "") { +- defines += [ "EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN=\"$eyeo_telemetry_activeping_auth_token\"" ] +- } else if (abp_telemetry_activeping_auth_token != "") { +- print("WARNING! abp_telemetry_activeping_auth_token is deprecated, " + +- "use eyeo_telemetry_activeping_auth_token instead.") +- eyeo_telemetry_activeping_auth_token = abp_telemetry_activeping_auth_token +- defines += [ "EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN=\"$eyeo_telemetry_activeping_auth_token\"" ] +- } else { +- print("WARNING! gn arg eyeo_telemetry_activeping_auth_token is not set. " + +- "Users will not be counted correctly by eyeo.") +- } +- +- if (eyeo_application_name != "") { +- defines += [ "EYEO_APPLICATION_NAME=\"$eyeo_application_name\"" ] +- } else if (abp_application_name != "") { +- print("WARNING! abp_application_name is deprecated, " + +- "use eyeo_application_name instead.") +- eyeo_application_name = abp_application_name +- defines += [ "EYEO_APPLICATION_NAME=\"$eyeo_application_name\"" ] +- } +- +- if (eyeo_application_version != "") { +- defines += [ "EYEO_APPLICATION_VERSION=\"$eyeo_application_version\"" ] +- } else if (abp_application_version != "") { +- print("WARNING! abp_application_version is deprecated, " + +- "use eyeo_application_version instead.") +- eyeo_application_version = abp_application_version +- defines += [ "EYEO_APPLICATION_VERSION=\"$eyeo_application_version\"" ] +- } +-} +- + source_set("core") { + output_name = "adblock_core" + sources = [ +- "activeping_telemetry_topic_provider.cc", +- "activeping_telemetry_topic_provider.h", + "adblock_controller.h", + "adblock_controller_impl.cc", + "adblock_controller_impl.h", + "adblock_switches.cc", + "adblock_switches.h", +- "adblock_telemetry_service.cc", +- "adblock_telemetry_service.h", + "features.cc", + "features.h", + "sitekey_storage.h", +@@ -155,8 +87,6 @@ source_set("core") { + "//components/adblock/core/subscription", + "//components/pref_registry:pref_registry", + ] +- +- all_dependent_configs = [ ":adblock_core_config" ] + } + + source_set("test_support") { +@@ -185,10 +115,6 @@ source_set("unit_tests") { + "test/sitekey_storage_impl_test.cc", + ] + +- if (eyeo_telemetry_client_id != "") { +- sources += [ "test/adblock_telemetry_service_unittest.cc" ] +- } +- + deps = [ + ":core", + ":test_support", +diff --git a/components/adblock/core/activeping_telemetry_topic_provider.cc b/components/adblock/core/activeping_telemetry_topic_provider.cc +deleted file mode 100644 +--- a/components/adblock/core/activeping_telemetry_topic_provider.cc ++++ /dev/null +@@ -1,206 +0,0 @@ +-/* +- * 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 . +- */ +- +-#include "components/adblock/core/activeping_telemetry_topic_provider.h" +- +-#include "base/guid.h" +-#include "base/json/json_reader.h" +-#include "base/json/json_writer.h" +-#include "base/system/sys_info.h" +-#include "base/time/time.h" +-#include "components/adblock/core/common/adblock_prefs.h" +- +-namespace adblock { +-namespace { +-constexpr base::TimeDelta kInitialDelay = base::Seconds(10); +-constexpr base::TimeDelta kNormalPingInterval = base::Hours(8); +-constexpr base::TimeDelta kRetryPingInterval = base::Hours(1); +- +-void AppendStringIfPresent(PrefService* pref_service, +- const std::string& pref_name, +- base::StringPiece payload_key, +- base::Value& payload) { +- auto str = pref_service->GetString(pref_name); +- if (!str.empty()) { +- payload.SetStringKey(payload_key, std::move(str)); +- } +-} +-} // namespace +- +-ActivepingTelemetryTopicProvider::ActivepingTelemetryTopicProvider( +- utils::AppInfo app_info, +- PrefService* pref_service, +- const GURL& base_url, +- const std::string& auth_token) +- : app_info_(std::move(app_info)), +- pref_service_(pref_service), +- base_url_(base_url), +- auth_token_(auth_token) {} +- +-ActivepingTelemetryTopicProvider::~ActivepingTelemetryTopicProvider() = default; +- +-// static +-GURL ActivepingTelemetryTopicProvider::DefaultBaseUrl() { +-#if !defined(EYEO_TELEMETRY_CLIENT_ID) +- LOG(WARNING) +- << "[eyeo] Using default Telemetry server since a Telemetry client ID " +- "was " +- "not provided. Users will not be counted correctly by eyeo. Please " +- "set an ID via \"eyeo_telemetry_client_id\" gn argument."; +-#endif +- return GURL(EYEO_TELEMETRY_SERVER_URL); +-} +- +-// static +-std::string ActivepingTelemetryTopicProvider::DefaultAuthToken() { +-#if defined(EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN) +- VLOG(1) << "[eyeo] Using " << EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN +- << " as Telemetry authentication token"; +- return EYEO_TELEMETRY_ACTIVEPING_AUTH_TOKEN; +-#else +- LOG(WARNING) +- << "[eyeo] No Telemetry authentication token defined. Users will " +- "not be counted correctly by eyeo. Please set a token via " +- "\"eyeo_telemetry_activeping_auth_token\" gn argument."; +- return ""; +-#endif +-} +- +-GURL ActivepingTelemetryTopicProvider::GetEndpointURL() const { +- return base_url_.Resolve("/topic/eyeochromium_activeping/version/1"); +-} +- +-std::string ActivepingTelemetryTopicProvider::GetAuthToken() const { +- return auth_token_; +-} +- +-std::string ActivepingTelemetryTopicProvider::GetPayload() const { +- base::Value payload(base::Value::Type::DICTIONARY); +- payload.SetStringKey("addon_name", "eyeo-chromium-sdk"); +- payload.SetStringKey("addon_version", "2.0.0"); +- payload.SetStringKey("application", app_info_.name); +- payload.SetStringKey("application_version", app_info_.version); +- payload.SetBoolKey("aa_active", +- pref_service_->GetBoolean(prefs::kEnableAcceptableAds)); +- payload.SetStringKey("platform", base::SysInfo::OperatingSystemName()); +- payload.SetStringKey("platform_version", +- base::SysInfo::OperatingSystemVersion()); +- // Server requires the following parameters to either have a correct, +- // non-empty value, or not be present at all. We shall not send empty strings. +- AppendStringIfPresent(pref_service_, prefs::kTelemetryLastPingTag, +- "last_ping_tag", payload); +- AppendStringIfPresent(pref_service_, prefs::kTelemetryFirstPingTime, +- "first_ping", payload); +- AppendStringIfPresent(pref_service_, prefs::kTelemetryLastPingTime, +- "last_ping", payload); +- AppendStringIfPresent(pref_service_, prefs::kTelemetryPreviousLastPingTime, +- "previous_last_ping", payload); +- +- base::Value root(base::Value::Type::DICTIONARY); +- root.SetKey("payload", std::move(payload)); +- std::string serialized; +- // The only way JSONWriter::Write() can return fail is then the Value +- // contains lists or dicts that are too deep (200 levels). We just built the +- // payload and root objects here, they should be really shallow. +- CHECK(base::JSONWriter::Write(root, &serialized)); +- VLOG(1) << "[eyeo] Telemetry ping payload: " << serialized; +- return serialized; +-} +- +-base::TimeDelta ActivepingTelemetryTopicProvider::GetTimeToNextRequest() const { +- const auto next_ping_time = +- pref_service_->GetTime(prefs::kTelemetryNextPingTime); +- // Next ping time may be unset if this is a first run. Next request should +- // happen soon, but not immediately to avoid interfering with first run load. +- if (next_ping_time.is_null()) +- return kInitialDelay; +- +- auto delay_to_next_ping = next_ping_time - base::Time::Now(); +- // Next ping can effectively be in the past. This happens ex. if the browser +- // was shut down for longer than the normal ping interval and is normal. +- // In that case, make the next ping soon, but not immediately, as to not +- // interfere with startup network traffic. +- return std::max(kInitialDelay, delay_to_next_ping); +-} +- +-void ActivepingTelemetryTopicProvider::ParseResponse( +- std::unique_ptr response_content) { +- if (!response_content) { +- VLOG(1) << "[eyeo] Telemetry ping failed, no response from server"; +- ScheduleNextPing(kRetryPingInterval); +- return; +- } +- +- VLOG(1) << "[eyeo] Response from Telemetry server: " << *response_content; +- auto parsed = base::JSONReader::Read(*response_content); +- if (!parsed || !parsed->is_dict()) { +- VLOG(1) +- << "[eyeo] Telemetry ping failed, response could not be parsed as JSON"; +- ScheduleNextPing(kRetryPingInterval); +- return; +- } +- +- auto* error_message = parsed->FindStringKey("error"); +- if (error_message) { +- VLOG(1) << "[eyeo] Telemetry ping failed, error message: " +- << *error_message; +- ScheduleNextPing(kRetryPingInterval); +- return; +- } +- +- // For legacy reasons, "ping_response_time" is sent to us as "token". This +- // should be the server time of when the ping was handled, possibly truncated +- // for anonymity. We don't parse it or interpret it, just send it back with +- // next ping. +- auto* ping_response_time = parsed->FindStringKey("token"); +- if (!ping_response_time) { +- VLOG(1) << "[eyeo] Telemetry ping failed, response did not contain a last " +- "ping / token value"; +- ScheduleNextPing(kRetryPingInterval); +- return; +- } +- +- VLOG(1) << "[eyeo] Telemetry ping succeeded"; +- ScheduleNextPing(kNormalPingInterval); +- UpdatePrefs(*ping_response_time); +-} +- +-void ActivepingTelemetryTopicProvider::ScheduleNextPing(base::TimeDelta delay) { +- pref_service_->SetTime(prefs::kTelemetryNextPingTime, +- base::Time::Now() + delay); +-} +- +-void ActivepingTelemetryTopicProvider::UpdatePrefs( +- const std::string& ping_response_time) { +- // First ping is only set once per client. +- if (pref_service_->GetString(prefs::kTelemetryFirstPingTime).empty()) { +- pref_service_->SetString(prefs::kTelemetryFirstPingTime, +- ping_response_time); +- } +- // Previous-to-last becomes last, last becomes current. +- pref_service_->SetString( +- prefs::kTelemetryPreviousLastPingTime, +- pref_service_->GetString(prefs::kTelemetryLastPingTime)); +- pref_service_->SetString(prefs::kTelemetryLastPingTime, ping_response_time); +- // Generate a new random tag that wil be sent along with ping times in the +- // next request. +- const auto tag = base::GUID::GenerateRandomV4(); +- pref_service_->SetString(prefs::kTelemetryLastPingTag, +- tag.AsLowercaseString()); +-} +- +-} // namespace adblock +diff --git a/components/adblock/core/activeping_telemetry_topic_provider.h b/components/adblock/core/activeping_telemetry_topic_provider.h +deleted file mode 100644 +--- a/components/adblock/core/activeping_telemetry_topic_provider.h ++++ /dev/null +@@ -1,72 +0,0 @@ +-/* +- * 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 . +- */ +- +-#ifndef COMPONENTS_ADBLOCK_CORE_ACTIVEPING_TELEMETRY_TOPIC_PROVIDER_H_ +-#define COMPONENTS_ADBLOCK_CORE_ACTIVEPING_TELEMETRY_TOPIC_PROVIDER_H_ +- +-#include "base/time/time.h" +-#include "components/adblock/core/adblock_telemetry_service.h" +-#include "components/adblock/core/common/adblock_utils.h" +-#include "components/prefs/pref_service.h" +- +-namespace adblock { +- +-// Telemetry topic provider that uploads user-counting data for periodic pings. +-// Provides the following data in Payload: +-// - Last ping time, previous-to-last ping time, first ping time +-// - Unique, non-persistent tag for disambiguating pings made by clients in +-// the same day +-// - Whether Acceptable Ads is enabled +-// - Application name & version, platform name & version +-// Note: Provides no user-identifiable information, no persistent tracking +-// data (ie. no traceable UUID) and no information about user actions. +-class ActivepingTelemetryTopicProvider final +- : public AdblockTelemetryService::TopicProvider { +- public: +- ActivepingTelemetryTopicProvider(utils::AppInfo app_info, +- PrefService* pref_service, +- const GURL& base_url, +- const std::string& auth_token); +- ~ActivepingTelemetryTopicProvider() final; +- +- static GURL DefaultBaseUrl(); +- static std::string DefaultAuthToken(); +- +- GURL GetEndpointURL() const final; +- std::string GetAuthToken() const final; +- std::string GetPayload() const final; +- +- // Normally 8 hours since last ping, 1 hour in case of retries. +- base::TimeDelta GetTimeToNextRequest() const final; +- +- // Attempts to parse "token" (an opaque server description of last ping time) +- // from |response_content|. +- void ParseResponse(std::unique_ptr response_content) final; +- +- private: +- void ScheduleNextPing(base::TimeDelta delay); +- void UpdatePrefs(const std::string& ping_response_time); +- +- const utils::AppInfo app_info_; +- PrefService* pref_service_; +- const GURL base_url_; +- const std::string auth_token_; +-}; +- +-} // namespace adblock +- +-#endif // COMPONENTS_ADBLOCK_CORE_ACTIVEPING_TELEMETRY_TOPIC_PROVIDER_H_ +diff --git a/components/adblock/core/adblock_controller_impl.cc b/components/adblock/core/adblock_controller_impl.cc +--- a/components/adblock/core/adblock_controller_impl.cc ++++ b/components/adblock/core/adblock_controller_impl.cc +@@ -397,7 +397,7 @@ void AdblockControllerImpl::InstallMissingSubscriptions( + subscriptions_in_service.begin(), subscriptions_in_service.end(), + std::back_inserter(subscriptions_to_install)); + for (const auto& sub : subscriptions_to_install) { +- DLOG(INFO) << "[eyeo] Installing missing subscription: " << sub; ++ LOG(INFO) << "[eyeo] Installing missing subscription: " << sub; + DownloadAndInstallSubscription(sub); + } + } +@@ -418,7 +418,7 @@ void AdblockControllerImpl::RemoveUnexpectedSubscriptions( + subscriptions_in_prefs.begin(), subscriptions_in_prefs.end(), + std::back_inserter(subscriptions_to_uninstall)); + for (const auto& sub : subscriptions_to_uninstall) { +- DLOG(INFO) << "[eyeo] Uninstalling unexpected subscription: " << sub; ++ LOG(INFO) << "[eyeo] Uninstalling unexpected subscription: " << sub; + UninstallSubscription(sub); + } + } +@@ -435,11 +435,11 @@ GURL AdblockControllerImpl::FindLanguageBasedRecommendedSubscription() const { + language_) != subscription.languages.end(); + }); + if (language_specific_subscription == recommended_subscriptions.end()) { +- DLOG(INFO) << "[eyeo] Using the default subscription for language \"" ++ LOG(INFO) << "[eyeo] Using the default subscription for language \"" + << language_ << "\""; + return DefaultSubscriptionUrl(); + } +- DLOG(INFO) << "[eyeo] Using recommended subscription for language \"" ++ LOG(INFO) << "[eyeo] Using recommended subscription for language \"" + << language_ << "\": " << language_specific_subscription->title; + return language_specific_subscription->url; + } +diff --git a/components/adblock/core/adblock_telemetry_service.cc b/components/adblock/core/adblock_telemetry_service.cc +deleted file mode 100644 +--- a/components/adblock/core/adblock_telemetry_service.cc ++++ /dev/null +@@ -1,216 +0,0 @@ +-/* +- * 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 . +- */ +- +-#include "components/adblock/core/adblock_telemetry_service.h" +- +-#include +- +-#include "base/bind.h" +-#include "base/strings/string_number_conversions.h" +-#include "base/strings/string_util.h" +-#include "base/strings/stringprintf.h" +-#include "base/strings/utf_string_conversions.h" +-#include "base/time/time.h" +-#include "base/timer/timer.h" +-#include "components/adblock/core/common/adblock_prefs.h" +-#include "components/prefs/pref_service.h" +-#include "net/base/load_flags.h" +-#include "services/network/public/cpp/resource_request.h" +-#include "services/network/public/cpp/simple_url_loader.h" +-#include "services/network/public/mojom/url_response_head.mojom.h" +- +-namespace adblock { +- +-namespace { +- +-const char kDataType[] = "application/json"; +-net::NetworkTrafficAnnotationTag kTrafficAnnotation = +- net::DefineNetworkTrafficAnnotation("adblock_telemetry_request", R"( +- semantics { +- sender: "AdblockTelemetryService" +- description: +- "Messages sent to telemetry.eyeo.com to report usage statistics." +- "Contain no user-identifiable data." +- trigger: +- "Periodic, several times a day." +- data: +- "Subject to change: " +- "Dates of first ping, last ping and previous-to-last ping. " +- "A non-persistent, unique ID that disambiguates pings made in the " +- "same day. " +- "Application name and version (ex. Chromium 86.0.4240.183). " +- "Platform name and version (ex. Windows 10). " +- "Whether Acceptable Ads are in use (yes/no)." +- destination: WEBSITE +- } +- policy { +- cookies_allowed: NO +- setting: +- "Enabled or disabled via 'Adblock Plus' setting." +- policy_exception_justification: +- "Parent setting may be controlled by policy" +- } +- })"); +- +-} // namespace +- +-// Represents an ongoing chain of requests relevant to a Topic. +-// A Topic is and endpoint on the Telemetry server that expects messages +-// about a domain of activity, ex. usage of Acceptable Ads or frequency of +-// filter "hits" per filter list. The browser may report on multiple topics. +-// Messages are sent periodically. The interval of communication and the +-// content of the messages is provided by a TopicProvider. +-class AdblockTelemetryService::Conversation { +- public: +- Conversation( +- std::unique_ptr topic_provider, +- scoped_refptr url_loader_factory) +- : topic_provider_(std::move(topic_provider)), +- url_loader_factory_(url_loader_factory) {} +- +- void Start() { +- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +- if (IsRunning()) +- return; +- ScheduleNextRequest(); +- } +- +- void Stop() { +- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +- if (!IsRunning()) +- return; +- timer_.Stop(); +- url_loader_.reset(); +- } +- +- bool IsRunning() const { return timer_.IsRunning() || url_loader_; } +- +- private: +- void ScheduleNextRequest() { +- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +- // A TopicProvider could return a negative time to next request. Clamp it +- // to "zero". +- const auto delay = +- std::max(topic_provider_->GetTimeToNextRequest(), base::TimeDelta()); +- VLOG(1) << "[eyeo] Next Telemetry request for " +- << topic_provider_->GetEndpointURL() << " scheduled for " +- << base::Time::Now() + delay; +- timer_.Start( +- FROM_HERE, delay, +- base::BindOnce(&Conversation::MakeRequest, base::Unretained(this))); +- } +- +- void MakeRequest() { +- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +- auto request = std::make_unique(); +- request->url = topic_provider_->GetEndpointURL(); +- VLOG(1) << "[eyeo] Sending request to: " << request->url; +- request->method = net::HttpRequestHeaders::kPostMethod; +- // The server expects authorization via a bearer token. The token may be +- // empty in testing builds. +- const auto auth_token = topic_provider_->GetAuthToken(); +- if (!auth_token.empty()) { +- request->headers.SetHeader(net::HttpRequestHeaders::kAuthorization, +- "Bearer " + auth_token); +- } +- // Notify the server we're expecting a JSON response. +- request->headers.SetHeader(net::HttpRequestHeaders::kAccept, kDataType); +- // Disallow using cache - identical requests should be physically sent to +- // the server. +- request->load_flags = net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE; +- // Omitting credentials prevents cookies from being sent. The server does +- // not expect or parse cookies, but we want to be on the safe side, +- // privacy-wise. +- request->credentials_mode = network::mojom::CredentialsMode::kOmit; +- +- // If any url_loader_ existed previously, it will be overwritten and its +- // request will be cancelled. +- url_loader_ = network::SimpleURLLoader::Create(std::move(request), +- kTrafficAnnotation); +- +- const auto payload = topic_provider_->GetPayload(); +- VLOG(2) << "[eyeo] Payload: " << payload; +- url_loader_->AttachStringForUpload(payload, kDataType); +- // The Telemetry server responds with a JSON that contains a description of +- // any potential error. We want to parse this JSON if possible, we're not +- // content with just an HTTP error code. Process the response content even +- // if the code is not 200. +- url_loader_->SetAllowHttpErrorResults(true); +- +- url_loader_->DownloadToString( +- url_loader_factory_.get(), +- base::BindOnce(&Conversation::OnResponseArrived, +- base::Unretained(this)), +- network::SimpleURLLoader::kMaxBoundedStringDownloadSize - 1); +- } +- +- void OnResponseArrived(std::unique_ptr server_response) { +- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +- topic_provider_->ParseResponse(std::move(server_response)); +- ScheduleNextRequest(); +- url_loader_.reset(); +- } +- +- SEQUENCE_CHECKER(sequence_checker_); +- std::unique_ptr topic_provider_; +- scoped_refptr url_loader_factory_; +- std::unique_ptr url_loader_; +- base::OneShotTimer timer_; +-}; +- +-AdblockTelemetryService::AdblockTelemetryService( +- PrefService* prefs, +- scoped_refptr url_loader_factory) +- : url_loader_factory_(url_loader_factory) { +- enable_adblock_.Init( +- prefs::kEnableAdblock, prefs, +- base::BindRepeating(&AdblockTelemetryService::OnEnableAdblockChanged, +- base::Unretained(this))); +-} +- +-AdblockTelemetryService::~AdblockTelemetryService() = default; +- +-void AdblockTelemetryService::AddTopicProvider( +- std::unique_ptr topic_provider) { +- ongoing_conversations_.push_back(std::make_unique( +- std::move(topic_provider), url_loader_factory_)); +-} +- +-void AdblockTelemetryService::Start() { +- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +- OnEnableAdblockChanged(); +-} +- +-void AdblockTelemetryService::OnEnableAdblockChanged() { +- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +- if (enable_adblock_.GetValue()) { +- VLOG(1) << "[eyeo] Starting periodic Telemetry requests"; +- for (auto& conversation : ongoing_conversations_) +- conversation->Start(); +- } else if (!enable_adblock_.GetValue()) { +- VLOG(1) << "[eyeo] Stopping periodic Telemetry requests"; +- for (auto& conversation : ongoing_conversations_) +- conversation->Stop(); +- } +-} +- +-void AdblockTelemetryService::Shutdown() { +- for (auto& conversation : ongoing_conversations_) +- conversation->Stop(); +-} +- +-} // namespace adblock +diff --git a/components/adblock/core/adblock_telemetry_service.h b/components/adblock/core/adblock_telemetry_service.h +deleted file mode 100644 +--- a/components/adblock/core/adblock_telemetry_service.h ++++ /dev/null +@@ -1,96 +0,0 @@ +-/* +- * 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 . +- */ +- +-#ifndef COMPONENTS_ADBLOCK_CORE_ADBLOCK_TELEMETRY_SERVICE_H_ +-#define COMPONENTS_ADBLOCK_CORE_ADBLOCK_TELEMETRY_SERVICE_H_ +- +-#include +-#include +-#include +- +-#include "base/sequence_checker.h" +-#include "base/time/time.h" +-#include "base/timer/timer.h" +-#include "components/keyed_service/core/keyed_service.h" +-#include "components/prefs/pref_member.h" +-#include "services/network/public/cpp/shared_url_loader_factory.h" +-#include "url/gurl.h" +- +-namespace network { +-class SimpleURLLoader; +-} // namespace network +- +-class PrefService; +- +-namespace adblock { +-/** +- * @brief Sends periodic pings to eyeo in order to count active users. Executed +- * from Browser process UI main thread. +- */ +-class AdblockTelemetryService : public KeyedService { +- public: +- // Provides data and behavior relevant for a Telemetry "topic". A topic could +- // be "counting users" or "reporting filter list hits" for example. +- class TopicProvider { +- public: +- virtual ~TopicProvider() = default; +- // Endpoint URL on the Telemetry server onto which requests should be sent. +- virtual GURL GetEndpointURL() const = 0; +- // Authorization bearer token for the endpoint defined by GetEndpointURL(). +- virtual std::string GetAuthToken() const = 0; +- // Data uploaded with the request, should be valid for the schema +- // present on the server. +- virtual std::string GetPayload() const = 0; +- // Returns the desired delay until AdblockTelemetryService makes the next +- // network request. +- virtual base::TimeDelta GetTimeToNextRequest() const = 0; +- // Parses the response returned by the Telemetry server. |response_content| +- // may be null. Implementation is free to implement a "retry" in case of +- // response errors via GetTimeToNextRequest(). +- virtual void ParseResponse( +- std::unique_ptr response_content) = 0; +- }; +- AdblockTelemetryService( +- PrefService* prefs, +- scoped_refptr url_loader_factory); +- ~AdblockTelemetryService() override; +- +- // Add all required topic providers before calling Start(). +- void AddTopicProvider(std::unique_ptr topic_provider); +- +- // Starts periodic Telemetry requests, provided ad-blocking is enabled. +- // If prefs::kAdblockEnabled is false, the schedule will instead start when +- // the pref becomes true. +- void Start(); +- +- // KeyedService: +- void Shutdown() override; +- +- private: +- void OnEnableAdblockChanged(); +- +- SEQUENCE_CHECKER(sequence_checker_); +- scoped_refptr url_loader_factory_; +- +- class Conversation; +- std::vector> ongoing_conversations_; +- BooleanPrefMember enable_adblock_; +-}; +- +-} // namespace adblock +- +-#endif // COMPONENTS_ADBLOCK_CORE_ADBLOCK_TELEMETRY_SERVICE_H_ +diff --git a/components/adblock/core/common/adblock_constants.cc b/components/adblock/core/common/adblock_constants.cc +--- a/components/adblock/core/common/adblock_constants.cc ++++ b/components/adblock/core/common/adblock_constants.cc +@@ -23,8 +23,6 @@ + + namespace adblock { + +-const char kSiteKeyHeaderKey[] = "x-adblock-key"; +- + const char kAllowlistEverythingFilter[] = "@@*$document"; + + const char kBlankHtml[] = +diff --git a/components/adblock/core/common/adblock_constants.h b/components/adblock/core/common/adblock_constants.h +--- a/components/adblock/core/common/adblock_constants.h ++++ b/components/adblock/core/common/adblock_constants.h +@@ -27,7 +27,6 @@ namespace flat { + enum AbpResource : int8_t; + } + +-extern const char kSiteKeyHeaderKey[]; + extern const char kAllowlistEverythingFilter[]; + + const std::string& CurrentSchemaVersion(); +diff --git a/components/adblock/core/common/adblock_prefs.cc b/components/adblock/core/common/adblock_prefs.cc +--- a/components/adblock/core/common/adblock_prefs.cc ++++ b/components/adblock/core/common/adblock_prefs.cc +@@ -67,47 +67,10 @@ const char kLastUsedSchemaVersion[] = "adblock.last_used_schema_version"; + // and for setting query parameters in subscription download requests. + const char kSubscriptionMetadata[] = "adblock.subscription_metadata"; + +-// Client-generated UUID4 that uniquely identifies the server response that +-// sent kTelemetryLastPingTime. Sent along with other ping times to +-// disambiguate between other clients who send ping requests the same day. +-// Regenerated on every successful response. +-const char kTelemetryLastPingTag[] = +- "adblock.telemetry.activeping.last_ping_tag"; +- +-// Server UTC time of last ping response, updated with every successful +-// response. Shall not be compared to client time (even UTC). Sent by the +-// telemetry server, stored as unparsed string (ex. "2022-02-08T09:30:00Z"). +-const char kTelemetryLastPingTime[] = +- "adblock.telemetry.activeping.last_ping_time"; +- +-// Previous last ping time, gets replaced by kTelemetryLastPingTime when a new +-// successful ping response arrives. Sent in a ping request. +-const char kTelemetryPreviousLastPingTime[] = +- "adblock.telemetry.activeping.previous_last_ping_time"; +- +-// Time of first recorded response for a telemetry ping request, sent along +-// with future ping requests, to further disambiguate +-// user-counting without being able to uniquely track a user. +-const char kTelemetryFirstPingTime[] = +- "adblock.telemetry.activeping.first_ping_time"; +- +-// Client time, when to perform the next ping? +-// Not sent, used locally to ensure we don't ping too often. +-const char kTelemetryNextPingTime[] = +- "adblock.telemetry.activeping.next_ping_time"; +- +-void RegisterTelemetryPrefs(PrefRegistrySimple* registry) { +- registry->RegisterStringPref(kTelemetryLastPingTag, ""); +- registry->RegisterStringPref(kTelemetryLastPingTime, ""); +- registry->RegisterStringPref(kTelemetryPreviousLastPingTime, ""); +- registry->RegisterStringPref(kTelemetryFirstPingTime, ""); +- registry->RegisterTimePref(kTelemetryNextPingTime, base::Time()); +-} +- + void RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterBooleanPref(kEnableAdblock, true); +- registry->RegisterBooleanPref(kEnableAcceptableAds, true); +- registry->RegisterBooleanPref(kAdblockMoreOptionsEnabled, false); ++ registry->RegisterBooleanPref(kEnableAcceptableAds, false); ++ registry->RegisterBooleanPref(kAdblockMoreOptionsEnabled, true); + registry->RegisterListPref(kAdblockAllowedDomains, {}); + registry->RegisterListPref(kAdblockCustomFilters, {}); + registry->RegisterListPref(kAdblockSubscriptions, {}); +@@ -119,7 +82,6 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterDictionaryPref(kSubscriptionSignatures); + registry->RegisterStringPref(kLastUsedSchemaVersion, ""); + registry->RegisterDictionaryPref(kSubscriptionMetadata); +- RegisterTelemetryPrefs(registry); + + VLOG(3) << "[eyeo] Registered prefs"; + } +diff --git a/components/adblock/core/common/adblock_utils.cc b/components/adblock/core/common/adblock_utils.cc +--- a/components/adblock/core/common/adblock_utils.cc ++++ b/components/adblock/core/common/adblock_utils.cc +@@ -49,16 +49,6 @@ std::string CreateDomainAllowlistingFilter(const std::string& domain) { + + SiteKey GetSitekeyHeader( + const scoped_refptr& headers) { +- size_t iterator = 0; +- std::string name; +- std::string value; +- while (headers->EnumerateHeaderLines(&iterator, &name, &value)) { +- std::transform(name.begin(), name.end(), name.begin(), +- [](unsigned char c) { return std::tolower(c); }); +- if (name == adblock::kSiteKeyHeaderKey) { +- return SiteKey{value}; +- } +- } + return {}; + } + +@@ -70,19 +60,6 @@ AppInfo::AppInfo(const AppInfo&) = default; + + AppInfo GetAppInfo() { + AppInfo info; +- +-#if defined(EYEO_APPLICATION_NAME) +- info.name = EYEO_APPLICATION_NAME; +-#else +- info.name = version_info::GetProductName(); +-#endif +-#if defined(EYEO_APPLICATION_VERSION) +- info.version = EYEO_APPLICATION_VERSION; +-#else +- info.version = version_info::GetVersionNumber(); +-#endif +- base::ReplaceChars(version_info::GetOSType(), base::kWhitespaceASCII, "", +- &info.client_os); + return info; + } + +diff --git a/components/adblock/core/converter/metadata.cc b/components/adblock/core/converter/metadata.cc +--- a/components/adblock/core/converter/metadata.cc ++++ b/components/adblock/core/converter/metadata.cc +@@ -38,7 +38,7 @@ bool ParseAdblockHeader(std::istream& stream) { + if (!re2::RE2::FullMatch( + re2::StringPiece(adblock_header.data(), adblock_header.size()), + adblock_header_re)) { +- DLOG(ERROR) ++ LOG(ERROR) + << "[eyeo] Invalid filter list. Should start with [Adblock Plus " + ".]. Won't parse."; + return false; +@@ -121,7 +121,7 @@ bool Metadata::ParseComment(const std::string& comment) { + if (redirect_url.is_valid()) { + redirect_url_ = redirect_url; + } else { +- DLOG(WARNING) << "[eyeo] Invalid redirect URL: " << value ++ LOG(WARNING) << "[eyeo] Invalid redirect URL: " << value + << ". Will not redirect."; + } + } else if (key == "title") +@@ -144,7 +144,7 @@ void Metadata::ParseExpirationTime(const std::string& expiration_value) { + if (!re2::RE2::FullMatch( + re2::StringPiece(expiration_value.data(), expiration_value.size()), + expiration_time_re, &expiration_time, &expiration_unit)) { +- DLOG(INFO) << "[eyeo] Invalid expiration time format: " << expiration_value ++ LOG(INFO) << "[eyeo] Invalid expiration time format: " << expiration_value + << ". Will use default value of " + << kDefaultExpirationInterval.InDays() << " days."; + return; +diff --git a/components/adblock/core/features.gni b/components/adblock/core/features.gni +deleted file mode 100644 +--- a/components/adblock/core/features.gni ++++ /dev/null +@@ -1,46 +0,0 @@ +-# +-# 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 . +- +-declare_args() { +- # eyeo Chromium SDK telemetry client id, provided on per-partner basis by eyeo. Used to +- # attribute usage reports to specific browsers. +- eyeo_telemetry_client_id = "" +- +- # eyeo Chromium SDK telemetry server address, by default evaluated to +- # "https://${eyeo_telemetry_client_id}.telemetry.eyeo.com/". +- # Override only for testing. +- eyeo_telemetry_server_url = "" +- +- # eyeo Chromium SDK telemetry authentication token, provided on per-partner basis by eyeo. +- eyeo_telemetry_activeping_auth_token = "" +- +- # eyeo Chromium SDK application name to be used in telemetry and +- # filter list download requests. If not set the value returned by +- # version_info::GetProductName() will be used instead. +- eyeo_application_name = "" +- +- # eyeo Chromium SDK application version to be used in telemetry and +- # filter list download requests. If not set the value returned by +- # version_info::GetVersionNumber() will be used instead. +- eyeo_application_version = "" +- +- # Deprecated telemetry gn args, will be removed in eyeo Chromium SDK version 107. +- abp_telemetry_client_id = "" +- abp_telemetry_server_url = "" +- abp_telemetry_activeping_auth_token = "" +- abp_application_name = "" +- abp_application_version = "" +-} +diff --git a/components/adblock/core/sitekey_storage_impl.cc b/components/adblock/core/sitekey_storage_impl.cc +--- a/components/adblock/core/sitekey_storage_impl.cc ++++ b/components/adblock/core/sitekey_storage_impl.cc +@@ -37,6 +37,8 @@ void SitekeyStorageImpl::ProcessResponseHeaders( + const GURL& request_url, + const scoped_refptr& headers, + const std::string& user_agent) { ++ // remove Acceptable Ads site key processing ++ if ((true)) return; + if (user_agent.empty()) { + LOG(WARNING) << "[eyeo] No user agent info"; + return; +@@ -66,6 +68,8 @@ SitekeyStorageImpl::FindSiteKeyForAnyUrl(const std::vector& urls) const { + void SitekeyStorageImpl::ProcessSiteKey(const GURL& request_url, + const SiteKey& site_key, + const std::string& user_agent) { ++ // remove Acceptable Ads site key processing ++ if ((true)) return; // simple caution, never invoked being private + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!site_key.value().empty()); + auto site_key_pair = FindSiteKeyForAnyUrl({request_url}); +@@ -116,6 +120,8 @@ bool SitekeyStorageImpl::IsSitekeySignatureValid( + const std::string& public_key_b64, + const std::string& signature_b64, + const std::string& data) const { ++ // remove Acceptable Ads site key ++ if ((true)) return false; // simple caution, never invoked being private + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + std::string signature; + if (!base::Base64Decode(signature_b64, &signature)) { +diff --git a/components/adblock/core/subscription/ongoing_subscription_request_impl.cc b/components/adblock/core/subscription/ongoing_subscription_request_impl.cc +--- a/components/adblock/core/subscription/ongoing_subscription_request_impl.cc ++++ b/components/adblock/core/subscription/ongoing_subscription_request_impl.cc +@@ -24,6 +24,7 @@ + #include "base/trace_event/trace_event.h" + #include "components/adblock/core/common/adblock_prefs.h" + #include "components/adblock/core/common/allowed_connection_type.h" ++#include "net/base/load_flags.h" + #include "net/http/http_request_headers.h" + #include "services/network/public/cpp/resource_request.h" + #include "services/network/public/mojom/url_response_head.mojom.h" +@@ -95,7 +96,7 @@ void OngoingSubscriptionRequestImpl::Start(GURL url, + if (IsConnectionAllowed()) { + StartInternal(); + } else { +- DLOG(INFO) << "[eyeo] Deferring download of " << url_ ++ LOG(INFO) << "[eyeo] Deferring download of " << url_ + << " due to current download policy."; + } + } +@@ -108,7 +109,7 @@ void OngoingSubscriptionRequestImpl::Retry() { + return; + } + backoff_entry_->InformOfRequest(false); +- DLOG(INFO) << "[eyeo] Will retry downloading " << url_ << " in " ++ LOG(INFO) << "[eyeo] Will retry downloading " << url_ << " in " + << backoff_entry_->GetTimeUntilRelease(); + retry_timer_->Start( + FROM_HERE, backoff_entry_->GetTimeUntilRelease(), +@@ -122,7 +123,7 @@ void OngoingSubscriptionRequestImpl::Redirect(GURL redirect_url) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(!url_.is_empty()) << "Redirect() called before Start()"; + DCHECK(url_ != redirect_url) << "Invalid redirect. Same URL"; +- DLOG(INFO) << "[eyeo] Will redirect " << url_ << " to " << redirect_url; ++ LOG(INFO) << "[eyeo] Will redirect " << url_ << " to " << redirect_url; + ++number_of_redirects_; + url_ = std::move(redirect_url); + StartInternal(); +@@ -180,10 +181,14 @@ void OngoingSubscriptionRequestImpl::StartInternal() { + // indefinitely. + return; + } +- DVLOG(1) << "[eyeo] Downloading " << url_; ++ LOG(INFO) << "[Adblock] Downloading " << url_; + auto request = std::make_unique(); + request->url = url_; + request->method = MethodToString(); ++ request->credentials_mode = network::mojom::CredentialsMode::kOmit; ++ request->load_flags = net::LOAD_BYPASS_CACHE | ++ net::LOAD_DISABLE_CACHE | net::LOAD_DO_NOT_SAVE_COOKIES | ++ net::LOAD_MINIMAL_HEADERS; + loader_ = + network::SimpleURLLoader::Create(std::move(request), kTrafficAnnotation); + +@@ -203,7 +208,7 @@ void OngoingSubscriptionRequestImpl::StartInternal() { + } + + void OngoingSubscriptionRequestImpl::StopInternal() { +- DLOG(INFO) << "[eyeo] Stopped downloading " << url_ ++ LOG(INFO) << "[eyeo] Stopped downloading " << url_ + << " due to current download policy."; + loader_.reset(); + retry_timer_->Stop(); +diff --git a/components/adblock/core/subscription/preloaded_subscription_provider_impl.cc b/components/adblock/core/subscription/preloaded_subscription_provider_impl.cc +--- a/components/adblock/core/subscription/preloaded_subscription_provider_impl.cc ++++ b/components/adblock/core/subscription/preloaded_subscription_provider_impl.cc +@@ -64,10 +64,10 @@ class PreloadedSubscriptionProviderImpl::SingleSubscriptionProvider { + utils::MakeFlatbufferDataFromResourceBundle( + info_.flatbuffer_resource_id), + Subscription::InstallationState::Preloaded, base::Time()); +- DLOG(INFO) << "[eyeo] Preloaded subscription now in use: " ++ LOG(INFO) << "[eyeo] Preloaded subscription now in use: " + << subscription_->GetSourceUrl(); + } else if (!needs_subscription && subscription_) { +- DLOG(INFO) << "[eyeo] Preloaded subscription no longer in use: " ++ LOG(INFO) << "[eyeo] Preloaded subscription no longer in use: " + << subscription_->GetSourceUrl(); + subscription_.reset(); + } +diff --git a/components/adblock/core/subscription/subscription_config.cc b/components/adblock/core/subscription/subscription_config.cc +--- a/components/adblock/core/subscription/subscription_config.cc ++++ b/components/adblock/core/subscription/subscription_config.cc +@@ -213,7 +213,7 @@ const std::vector& config::GetKnownSubscriptions() { + "ABP filters", + {}, + SubscriptionUiVisibility::Visible, +- SubscriptionFirstRunBehavior::Subscribe, ++ SubscriptionFirstRunBehavior::Ignore, + SubscriptionPrivilegedFilterStatus::Allowed}, + {GURL("https://easylist-downloads.adblockplus.org/" + "i_dont_care_about_cookies.txt"), +@@ -278,6 +278,8 @@ const std::vector& config::GetKnownSubscriptions() { + } + + bool config::AllowPrivilegedFilters(const GURL& url) { ++ // Always forbid snippets and header filters ++ if ((true)) return false; + for (const auto& cur : GetKnownSubscriptions()) { + if (cur.url == url) { + return cur.privileged_status == +@@ -291,9 +293,7 @@ bool config::AllowPrivilegedFilters(const GURL& url) { + const std::vector& + config::GetPreloadedSubscriptionConfiguration() { + static const std::vector preloaded_subscriptions = +- {{"*easylist.txt", IDR_ADBLOCK_FLATBUFFER_EASYLIST}, +- {"*exceptionrules.txt", IDR_ADBLOCK_FLATBUFFER_EXCEPTIONRULES}, +- {"*abp-filters-anti-cv.txt", IDR_ADBLOCK_FLATBUFFER_ANTICV}}; ++ {}; + return preloaded_subscriptions; + } + +diff --git a/components/adblock/core/subscription/subscription_downloader_impl.cc b/components/adblock/core/subscription/subscription_downloader_impl.cc +--- a/components/adblock/core/subscription/subscription_downloader_impl.cc ++++ b/components/adblock/core/subscription/subscription_downloader_impl.cc +@@ -56,6 +56,7 @@ GURL AddUrlParameters(const GURL& subscription_url, + const SubscriptionPersistentMetadata* persistent_metadata, + const utils::AppInfo& client_metadata, + const bool is_disabled) { ++ if ((true)) return subscription_url; + const std::string query = base::StrCat( + {"addonName=", "eyeo-chromium-sdk", "&addonVersion=", "1.0", + "&application=", base::EscapeQueryParamValue(client_metadata.name, true), +@@ -140,10 +141,6 @@ void SubscriptionDownloaderImpl::DoHeadRequest( + + bool SubscriptionDownloaderImpl::IsUrlAllowed( + const GURL& subscription_url) const { +- if (net::IsLocalhost(subscription_url)) { +- // We trust all localhost urls, regardless of scheme. +- return true; +- } + if (!subscription_url.SchemeIs("https") && + !subscription_url.SchemeIs("data")) { + return false; +@@ -193,11 +190,11 @@ void SubscriptionDownloaderImpl::OnDownloadFinished( + persistent_metadata_->IncrementDownloadErrorCount(subscription_url); + if (std::get(download_it->second) == + RetryPolicy::RetryUntilSucceeded) { +- DLOG(WARNING) << "[eyeo] Failed to retrieve content for " ++ LOG(WARNING) << "[eyeo] Failed to retrieve content for " + << subscription_url << ", will retry"; + std::get(download_it->second)->Retry(); + } else { +- DLOG(WARNING) << "[eyeo] Failed to retrieve content for " ++ LOG(WARNING) << "[eyeo] Failed to retrieve content for " + << subscription_url << ", will abort"; + std::move(std::get(download_it->second)) + .Run(nullptr); +@@ -230,14 +227,14 @@ void SubscriptionDownloaderImpl::OnConversionFinished( + TRACE_ID_LOCAL(GenerateTraceId(subscription_url))); + const auto download_it = ongoing_downloads_.find(subscription_url); + if (download_it == ongoing_downloads_.end()) { +- VLOG(1) << "[eyeo] Conversion result discarded, subscription download " ++ LOG(WARNING) << "[eyeo] Conversion result discarded, subscription download " + "was cancelled."; + return; + } + + switch (converter_result.status) { + case ConverterResult::Ok: +- VLOG(1) << "[eyeo] Finished converting " << subscription_url ++ LOG(WARNING) << "[eyeo] Finished converting " << subscription_url + << " successfully"; + std::move(std::get(download_it->second)) + .Run(std::move(converter_result.data)); +@@ -279,7 +276,7 @@ void SubscriptionDownloaderImpl::AbortWithWarning( + const std::string& warning) { + if (ongoing_download_it == ongoing_downloads_.end()) + return; +- DLOG(WARNING) << "[eyeo] " << warning << " Aborting download of " ++ LOG(WARNING) << "[eyeo] " << warning << " Aborting download of " + << ongoing_download_it->first; + std::move(std::get(ongoing_download_it->second)) + .Run(nullptr); +diff --git a/components/adblock/core/subscription/subscription_persistent_storage_impl.cc b/components/adblock/core/subscription/subscription_persistent_storage_impl.cc +--- a/components/adblock/core/subscription/subscription_persistent_storage_impl.cc ++++ b/components/adblock/core/subscription/subscription_persistent_storage_impl.cc +@@ -113,6 +113,8 @@ SubscriptionPersistentStorageImpl::ReadSubscriptionsFromDirectory( + if (!base::ReadFileToString(flatbuffer_path, &contents)) { + // File could not be read. + base::DeleteFile(flatbuffer_path); ++ LOG(INFO) << "[eyeo] Deleting " << flatbuffer_path.BaseName().AsUTF8Unsafe() ++ << "reason: File could not be read"; + continue; + } + TRACE_EVENT_END1("eyeo", "ReadFileToString", "path", +@@ -120,6 +122,8 @@ SubscriptionPersistentStorageImpl::ReadSubscriptionsFromDirectory( + TRACE_EVENT_BEGIN0("eyeo", "VerifySubscriptionBuffer"); + if (!validator->IsSignatureValid( + InMemoryFlatbufferData(std::move(contents)), flatbuffer_path)) { ++ LOG(INFO) << "[eyeo] Deleting " << flatbuffer_path.BaseName().AsUTF8Unsafe() ++ << "reason: This is not a valid subscription file"; + // This is not a valid subscription file, remove it. + base::DeleteFile(flatbuffer_path); + continue; +diff --git a/components/adblock/core/subscription/subscription_service.h b/components/adblock/core/subscription/subscription_service.h +--- a/components/adblock/core/subscription/subscription_service.h ++++ b/components/adblock/core/subscription/subscription_service.h +@@ -65,10 +65,6 @@ class SubscriptionService : public KeyedService { + virtual void DownloadAndInstallSubscription( + const GURL& subscription_url, + InstallationCallback on_finished) = 0; +- // Does an HEAD request on acceptable ads subscription with last known version +- // and stores received version +- // TODO(mpawlowski): Remove in DPD-1154. +- virtual void PingAcceptableAds(PingCallback on_finished) = 0; + // Removes a previously installed subscription with GetSourceUrl() == + // |subscription_url| both from in-memory state and from persistent storage. + virtual void UninstallSubscription(const GURL& subscription_url) = 0; +diff --git a/components/adblock/core/subscription/subscription_service_impl.cc b/components/adblock/core/subscription/subscription_service_impl.cc +--- a/components/adblock/core/subscription/subscription_service_impl.cc ++++ b/components/adblock/core/subscription/subscription_service_impl.cc +@@ -185,31 +185,22 @@ void SubscriptionServiceImpl::DownloadAndInstallSubscription( + ongoing_installation)); + } + +-void SubscriptionServiceImpl::PingAcceptableAds(PingCallback on_finished) { +- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +- DCHECK(IsInitialized()); +- downloader_->DoHeadRequest( +- AcceptableAdsUrl(), +- base::BindOnce(&SubscriptionServiceImpl::OnHeadRequestDone, +- weak_ptr_factory_.GetWeakPtr(), std::move(on_finished))); +-} +- + void SubscriptionServiceImpl::UninstallSubscription( + const GURL& subscription_url) { +- DVLOG(1) << "[eyeo] Removing subscription " << subscription_url; ++ LOG(INFO) << "[eyeo] Removing subscription " << subscription_url; + if (!UninstallSubscriptionInternal(subscription_url)) { + VLOG(1) << "[eyeo] Nothing to remove, subscription not installed " + << subscription_url; + return; + }; +- if (subscription_url != AcceptableAdsUrl()) { ++ if ((true) || subscription_url != AcceptableAdsUrl()) { + // Remove metadata associated with the subscription. Retain (forever) + // metadata of the Acceptable Ads subscription even when it's no longer + // installed, to allow continued HEAD-only pings for user counting purposes. + persistent_metadata_->RemoveMetadata(subscription_url); + } + UpdatePreloadedSubscriptionProvider(); +- VLOG(1) << "[eyeo] Removed subscription " << subscription_url; ++ LOG(INFO) << "[eyeo] Removed subscription " << subscription_url; + } + + void SubscriptionServiceImpl::SetCustomFilters( +diff --git a/components/adblock/core/subscription/subscription_service_impl.h b/components/adblock/core/subscription/subscription_service_impl.h +--- a/components/adblock/core/subscription/subscription_service_impl.h ++++ b/components/adblock/core/subscription/subscription_service_impl.h +@@ -58,7 +58,6 @@ class SubscriptionServiceImpl final : public SubscriptionService { + std::unique_ptr GetCurrentSnapshot() const final; + void DownloadAndInstallSubscription(const GURL& subscription_url, + InstallationCallback on_finished) final; +- void PingAcceptableAds(PingCallback on_finished) final; + void UninstallSubscription(const GURL& subscription_url) final; + void SetCustomFilters(const std::vector& filters) final; + +diff --git a/components/adblock/core/subscription/subscription_updater_impl.cc b/components/adblock/core/subscription/subscription_updater_impl.cc +--- a/components/adblock/core/subscription/subscription_updater_impl.cc ++++ b/components/adblock/core/subscription/subscription_updater_impl.cc +@@ -74,19 +74,19 @@ void SubscriptionUpdaterImpl::SynchronizeWithPrefState() { + return; + } + if (enable_adblock_.GetValue() && !timer_.IsRunning()) { +- DLOG(INFO) << "[eyeo] Starting update schedule, first check scheduled for " ++ LOG(INFO) << "[eyeo] Starting update schedule, first check scheduled for " + << base::Time::Now() + initial_delay_; + timer_.Start(FROM_HERE, initial_delay_, + base::BindOnce(&SubscriptionUpdaterImpl::RunUpdateCheck, + weak_ptr_factory_.GetWeakPtr())); + } else if (!enable_adblock_.GetValue() && timer_.IsRunning()) { +- DLOG(INFO) << "[eyeo] Stopping update schedule"; ++ LOG(INFO) << "[eyeo] Stopping update schedule"; + timer_.Stop(); + } + } + + void SubscriptionUpdaterImpl::RunUpdateCheck() { +- DLOG(INFO) << "[eyeo] Running subscription update check"; ++ LOG(INFO) << "[eyeo] Running subscription update check"; + const auto available_subscriptions = + subscription_service_->GetCurrentSubscriptions(); + for (const auto& subscription : available_subscriptions) { +@@ -98,12 +98,12 @@ void SubscriptionUpdaterImpl::RunUpdateCheck() { + } + + if (persistent_metadata_->IsExpired(subscription->GetSourceUrl())) { +- DVLOG(1) << "[eyeo] Downloading update for subscription " ++ LOG(INFO) << "[eyeo] Downloading update for subscription " + << subscription->GetSourceUrl(); + subscription_service_->DownloadAndInstallSubscription( + subscription->GetSourceUrl(), base::DoNothing()); + } else { +- DVLOG(1) << "[eyeo] Subscription " << subscription->GetSourceUrl() ++ LOG(INFO) << "[eyeo] Subscription " << subscription->GetSourceUrl() + << " not expired yet, not updating"; + } + } +@@ -118,23 +118,6 @@ void SubscriptionUpdaterImpl::RunUpdateCheck() { + + void SubscriptionUpdaterImpl::SendPingIfNecessary( + const std::vector>& available_subscriptions) { +- // When an Acceptable Ads subscription is not installed, we will not send an +- // update download request. But to know how many users have AA disabled, +- // we send a special HEAD request, or a ping. It contains the same data as +- // a download request, but the response has no payload. +- const bool has_acceptable_ads = +- base::ranges::find(available_subscriptions, AcceptableAdsUrl(), +- &Subscription::GetSourceUrl) != +- available_subscriptions.end(); +- if (!has_acceptable_ads) { +- if (persistent_metadata_->IsExpired(AcceptableAdsUrl())) { +- DLOG(INFO) << "[eyeo] Acceptable Ads disabled, sending ping"; +- subscription_service_->PingAcceptableAds(base::DoNothing()); +- } else { +- DLOG(INFO) +- << "[eyeo] Acceptable Ads disabled, subscription not expired yet"; +- } +- } + } + + } // namespace adblock +diff --git a/components/adblock/core/subscription/subscription_validator_impl.cc b/components/adblock/core/subscription/subscription_validator_impl.cc +--- a/components/adblock/core/subscription/subscription_validator_impl.cc ++++ b/components/adblock/core/subscription/subscription_validator_impl.cc +@@ -65,9 +65,7 @@ SubscriptionValidatorImpl::SubscriptionValidatorImpl( + main_thread_task_runner_(std::move(main_thread_task_runner)) { + ClearSignaturesIfSchemaVersionChanged(pref_service_, current_schema_version); + initial_subscription_signatures_ = +- pref_service_->GetDict(prefs::kSubscriptionSignatures).Clone(); +- initial_subscription_signatures_ = +- pref_service_->GetDict(prefs::kSubscriptionSignatures).Clone(); ++ pref_service_->GetValueDict(prefs::kSubscriptionSignatures).Clone(); + } + + SubscriptionValidatorImpl::~SubscriptionValidatorImpl() = default; +@@ -78,11 +76,11 @@ bool SubscriptionValidatorImpl::IsSignatureValid( + const auto* expected_hash = initial_subscription_signatures_.FindString( + path.BaseName().AsUTF8Unsafe()); + if (!expected_hash) { +- DLOG(WARNING) << "[eyeo] " << path << " has no matching signature in prefs"; ++ LOG(WARNING) << "[eyeo] " << path.BaseName().AsUTF8Unsafe() << " has no matching signature in prefs"; + return false; + } + if (*expected_hash != ComputeSubscriptionHash(data)) { +- DLOG(WARNING) << "[eyeo] " << path << " has invalid signature in prefs"; ++ LOG(WARNING) << "[eyeo] " << path.BaseName().AsUTF8Unsafe() << " has invalid signature in prefs"; + return false; + } + return true; +diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn +--- a/components/resources/BUILD.gn ++++ b/components/resources/BUILD.gn +@@ -68,7 +68,6 @@ grit("components_resources") { + + deps += [ + "//components/resources/adblocking:copy_snippets_lib", +- "//components/resources/adblocking:make_all_preloaded_subscriptions", + ] + } + +diff --git a/components/resources/adblock_resources.grdp b/components/resources/adblock_resources.grdp +--- a/components/resources/adblock_resources.grdp ++++ b/components/resources/adblock_resources.grdp +@@ -17,7 +17,4 @@ + + + +- +- +- + +diff --git a/components/resources/adblocking/.gitignore b/components/resources/adblocking/.gitignore +--- a/components/resources/adblocking/.gitignore ++++ b/components/resources/adblocking/.gitignore +@@ -1 +1 @@ +-snippets ++#snippets +diff --git a/components/resources/adblocking/BUILD.gn b/components/resources/adblocking/BUILD.gn +--- a/components/resources/adblocking/BUILD.gn ++++ b/components/resources/adblocking/BUILD.gn +@@ -18,7 +18,7 @@ import("//build/compiled_action.gni") + + # Converts text-format filter lists into flatbuffers using a standalone + # converter tool. +-template("make_preloaded_subscription") { ++template("make_preloaded_subscription_NO") { + compiled_action(target_name) { + tool = "//components/adblock/core/converter:adblock_flatbuffer_converter" + inputs = [ invoker.input ] +@@ -33,29 +33,8 @@ template("make_preloaded_subscription") { + + # Note, url is *not* used to download the list during build time, only to + # identify the subscription. Consider it metadata. +-make_preloaded_subscription("make_easylist") { +- input = "//components/resources/adblocking/easylist.txt" +- url = "https://easylist-downloads.adblockplus.org/easylist.txt" +- output = "${target_gen_dir}/easylist.fb" +-} +- +-make_preloaded_subscription("make_exceptionrules") { +- input = "//components/resources/adblocking/exceptionrules.txt" +- url = "https://easylist-downloads.adblockplus.org/exceptionrules.txt" +- output = "${target_gen_dir}/exceptionrules.fb" +-} +- +-make_preloaded_subscription("make_anticv") { +- input = "//components/resources/adblocking/anticv.txt" +- url = "https://easylist-downloads.adblockplus.org/abp-filters-anti-cv.txt" +- output = "${target_gen_dir}/anticv.fb" +-} +- +-group("make_all_preloaded_subscriptions") { ++group("make_all_preloaded_subscriptions_NO") { + deps = [ +- ":make_anticv", +- ":make_easylist", +- ":make_exceptionrules", + ] + } + +diff --git a/components/resources/adblocking/snippets/dist/isolated-first.jst b/components/resources/adblocking/snippets/dist/isolated-first.jst +new file mode 100755 +--- /dev/null ++++ b/components/resources/adblocking/snippets/dist/isolated-first.jst +@@ -0,0 +1,62 @@ ++(e, ...t) => { ++/*! ++ * This file is part of eyeo's Anti-Circumvention Snippets module (@eyeo/snippets), ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * @eyeo/snippets 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/snippets 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/snippets. If not, see . ++ */ ++ ((environment, ...filters) => { ++const e=Proxy,{apply:t,bind:n,call:r}=Function,o=r.bind(t),i=r.bind(n),s=r.bind(r),l={get:(e,t)=>i(r,e[t])},a=t=>new e(t,l),c={get:(e,t)=>i(e[t],e)},u=t=>new e(t,c),{assign:f,defineProperties:d,freeze:p,getOwnPropertyDescriptor:h,getOwnPropertyDescriptors:w,getPrototypeOf:g}=u(Object);a({});const{species:b}=Symbol,m={get(e,t){const n=e[t];class r extends n{}const o=w(n.prototype);delete o.constructor,p(d(r.prototype,o));const i=w(n);return delete i.length,delete i.prototype,i[b]={value:r},p(d(r,i))}},y=t=>new e(t,m),v="undefined"!=typeof environment?environment:{};"undefined"==typeof globalThis&&(window.globalThis=window);const{apply:S,ownKeys:E}=u(Reflect),x="world"in v,M=x&&"ISOLATED"===v.world,T=x&&"MAIN"===v.world,k="object"==typeof chrome&&!!chrome.runtime,P="object"==typeof browser&&!!browser.runtime,O=!T&&(M||k||P),D=e=>O?e:C(e,R(e)),{create:C,defineProperties:W,defineProperty:N,freeze:L,getOwnPropertyDescriptor:A,getOwnPropertyDescriptors:R}=u(Object),V=u(globalThis),I=O?globalThis:y(globalThis),{Map:j,RegExp:H,Set:$,WeakMap:_,WeakSet:B}=I,F=(e,t,n=null)=>{const r=E(t);for(const o of E(e)){if(r.includes(o))continue;const i=A(e,o);if(n&&"value"in i){const{value:e}=i;"function"==typeof e&&(i.value=n(e))}N(t,o,i)}},z=e=>{const t=I[e];class n extends t{}const{toString:r,valueOf:o}=t.prototype;W(n.prototype,{toString:{value:r},valueOf:{value:o}});const i=e.toLowerCase(),s=e=>function(){const t=S(e,this,arguments);return typeof t===i?new n(t):t};return F(t,n,s),F(t.prototype,n.prototype,s),n},X=L({frozen:new _,hidden:new B,iframePropertiesToAbort:{read:new $,write:new $},abortedIframes:new _}),q=new H("^[A-Z]");var J=new Proxy(new j([["chrome",O&&(k&&chrome||P&&browser)||void 0],["isExtensionContext",O],["variables",X],["console",D(console)],["document",globalThis.document],["performance",D(performance)],["JSON",D(JSON)],["Map",j],["Math",D(Math)],["Number",O?Number:z("Number")],["RegExp",H],["Set",$],["String",O?String:z("String")],["WeakMap",_],["WeakSet",B],["MouseEvent",MouseEvent]]),{get(e,t){if(e.has(t))return e.get(t);let n=globalThis[t];return"function"==typeof n&&(n=(q.test(t)?I:V)[t]),e.set(t,n),n},has:(e,t)=>e.has(t)});const U={WeakSet:WeakSet,WeakMap:WeakMap,WeakValue:class{has(){return!1}set(){}}},{apply:G}=Reflect;const{Map:K,WeakMap:Y,WeakSet:Z,setTimeout:Q}=J;let ee=!0,te=e=>{e.clear(),ee=!ee};var ne=function(e){const{WeakSet:t,WeakMap:n,WeakValue:r}=this||U,o=new t,i=new n,s=new r;return function(t){if(o.has(t))return t;if(i.has(t))return i.get(t);if(s.has(t))return s.get(t);const n=G(e,this,arguments);return o.add(n),n!==t&&("object"==typeof t&&t?i:s).set(t,n),n}}.bind({WeakMap:Y,WeakSet:Z,WeakValue:class extends K{set(e,t){return ee&&(ee=!ee,Q(te,0,this)),super.set(e,t)}}});const{concat:re,includes:oe,join:ie,reduce:se,unshift:le}=a([]),ae=y(globalThis),{Map:ce,WeakMap:ue}=ae,fe=new ce,de=t=>{const n=(e=>{const t=[];let n=e;for(;n;){if(fe.has(n))le(t,fe.get(n));else{const e=w(n);fe.set(n,e),le(t,e)}n=g(n)}return le(t,{}),o(f,null,t)})("function"==typeof t?t.prototype:t),r={get(e,t){if(t in n){const{value:r,get:o}=n[t];if(o)return s(o,e);if("function"==typeof r)return i(r,e)}return e[t]},set(e,t,r){if(t in n){const{set:o}=n[t];if(o)return s(o,e,r),!0}return e[t]=r,!0}};return t=>new e(t,r)},{isExtensionContext:pe,Array:he,Number:we,String:ge,Object:be}=J,{isArray:me}=he,{getOwnPropertyDescriptor:ye,setPrototypeOf:ve}=be,{toString:Se}=be.prototype,{slice:Ee}=ge.prototype,{get:xe}=ye(Node.prototype,"nodeType"),Me=pe?{}:{Attr:de(Attr),CanvasRenderingContext2D:de(CanvasRenderingContext2D),CSSStyleDeclaration:de(CSSStyleDeclaration),Document:de(Document),Element:de(Element),HTMLCanvasElement:de(HTMLCanvasElement),HTMLElement:de(HTMLElement),HTMLImageElement:de(HTMLImageElement),HTMLScriptElement:de(HTMLScriptElement),MutationRecord:de(MutationRecord),Node:de(Node),ShadowRoot:de(ShadowRoot),get CSS2Properties(){return Me.CSSStyleDeclaration}},Te=(e,t)=>{if("Element"!==t&&t in Me)return Me[t](e);if(me(e))return ve(e,he.prototype);const n=(e=>s(Ee,s(Se,e),8,-1))(e);if(n in Me)return Me[n](e);if(n in J)return ve(e,J[n].prototype);if("nodeType"in e)switch(s(xe,e)){case 1:if(!(t in Me))throw new Error("unknown hint "+t);return Me[t](e);case 2:return Me.Attr(e);case 3:return Me.Node(e);case 9:return Me.Document(e)}throw new Error("unknown brand "+n)};var ke=pe?e=>e===window||e===globalThis?J:e:ne(((e,t="Element")=>{if(e===window||e===globalThis)return J;switch(typeof e){case"object":return e&&Te(e,t);case"string":return new ge(e);case"number":return new we(e);default:throw new Error("unsupported value")}}));let{document:Pe,getComputedStyle:Oe,isExtensionContext:De,variables:Ce,Array:We,MutationObserver:Ne,Object:Le,XPathEvaluator:Ae,XPathExpression:Re,XPathResult:Ve}=ke(window),{querySelectorAll:Ie}=Pe,je=Ie&&i(Ie,Pe);const{assign:He,setPrototypeOf:$e}=Le;class _e extends Re{evaluate(...e){return $e(o(super.evaluate,this,e),Ve.prototype)}}class Be extends Ae{createExpression(...e){return $e(o(super.createExpression,this,e),_e.prototype)}}function Fe(e){if(Ce.hidden.has(e))return;!function(e){De&&"function"==typeof checkElement&&checkElement(e)}(e),Ce.hidden.add(e);let{style:t}=ke(e),n=ke(t,"CSSStyleDeclaration"),r=ke([]),{debugCSSProperties:o}=v;for(let[e,t]of o||[["display","none"]])n.setProperty(e,t,"important"),r.push([e,n.getPropertyValue(e)]);new Ne((()=>{for(let[e,t]of r){let r=n.getPropertyValue(e),o=n.getPropertyPriority(e);r==t&&"important"==o||n.setProperty(e,t,"important")}})).observe(e,{attributes:!0,attributeFilter:["style"]})}function ze(e){let t=e;if(t.startsWith("xpath(")&&t.endsWith(")")){let e=t.slice(6,-1),n=(new Be).createExpression(e,null),r=Ve.ORDERED_NODE_SNAPSHOT_TYPE;return e=>{if(!e)return;let t=n.evaluate(Pe,r,null),{snapshotLength:o}=t;for(let n=0;nje(e).forEach(t)}function Xe(e,t,n){let r;null==n&&(n=t);const o=()=>{for(const o of je(n)){const n=ke(o).closest(t);n&&e(o,n)&&(r(),Fe(n))}};return He(new Ne(o),{race(e){r=e,this.observe(Pe,{childList:!0,characterData:!0,subtree:!0}),o()}})}function qe(e,t,n){let r=ke(t,"CSSStyleDeclaration");if("none"==r.getPropertyValue("display"))return!1;let o=r.getPropertyValue("visibility");if("hidden"==o||"collapse"==o)return!1;if(!n||e==n)return!0;let i=ke(e).parentElement;return!i||qe(i,Oe(i),n)}function Je(e){let t=Oe(e),{cssText:n}=t;if(n)return n;for(let e of t)n+=`${e}: ${t[e]}; `;return ke(n).trim()}let{parseInt:Ue,setTimeout:Ge,Error:Ke,MouseEvent:Ye,MutationObserver:Ze,WeakSet:Qe}=ke(window);let{Math:et,RegExp:tt}=ke(window);function nt(e){let{length:t}=e;if(t>1&&"/"===e[0]){let n="/"===e[t-1];if(n||t>2&&ke(e).endsWith("/i")){let t=[ke(e).slice(1,n?-1:-2)];return n||t.push("i"),new tt(...t)}}return new tt(ke(e).replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))}let rt=!1;function ot(){return rt}const{console:it}=ke(window),st=()=>{};function lt(...e){ot()&&ke(e).unshift("%c DEBUG","font-weight: bold"),it.log(...e)}function at(e){return i(ot()?lt:st,null,e)}let{Array:ct,Error:ut,Map:ft,parseInt:dt}=ke(window),pt=null,ht=null;function wt(e,t){if(null===pt)return st;let n=pt,{participants:r}=n;return r.set(o,t),o;function o(){if(n.winners<1)return;if(at("race")(`${e} won the race`),n===pt)ht.push(o);else if(r.delete(o),--n.winners<1){for(let e of r.values())e();r.clear()}}}let{MutationObserver:gt}=ke(window);let{clearTimeout:bt,fetch:mt,getComputedStyle:yt,setTimeout:vt,Map:St,MutationObserver:Et,Uint8Array:xt}=ke(window);let Mt=new St;function Tt(e,{as:t="arrayBuffer",cleanup:n=6e4}={}){let r=t+":"+e,o=Mt.get(r)||{remove:()=>Mt.delete(r),result:null,timer:0};return bt(o.timer),o.timer=vt(o.remove,n),o.result||(o.result=mt(e).then((e=>e[t]())).catch(o.remove),Mt.set(r,o)),o.result}const{parseFloat:kt,Math:Pt,MutationObserver:Ot,WeakSet:Dt}=ke(window),{min:Ct}=Pt,Wt=(e,t)=>{const n=e.length+1,r=t.length+1,o=[[0]];let i=0,s=0;for(;++i"{mark(){},end(){}}"};let{MutationObserver:Ft}=ke(window);const{ELEMENT_NODE:zt}=Node;const Xt={log:lt,race:function(e,t="1"){switch(e){case"start":pt={winners:dt(t,10)||1,participants:new ft},ht=new ct;break;case"end":case"finish":case"stop":pt=null;for(let e of ht)e();ht=null;break;default:throw new ut(`Invalid action: ${e}`)}},debug:function(){rt=!0},"hide-if-matches-xpath":function(e){let{mark:t,end:n}=Bt,r=ze(`xpath(${e})`),o=()=>{t(),r((e=>{s(),ke(e).nodeType===zt?Fe(e):ke(e).textContent=""})),n()},i=new Ft(o),s=wt("hide-if-matches-xpath",(()=>i.disconnect()));i.observe(document,{characterData:!0,childList:!0,subtree:!0}),o()},"hide-if-contains":function(e,t="*",n=null){let r=nt(e);const o=Xe((e=>r.test(ke(e).textContent)),t,n);o.race(wt("hide-if-contains",(()=>{o.disconnect()})))},"hide-if-contains-similar-text":function(e,t,n=null,r=0,o=0){const i=new Dt,s=at("hide-if-contains-similar-text"),l=ke(e),{length:a}=l,c=a+kt(r)||0,u=ke([...l]).sort(),f=kt(o)||1/0;null==n&&(n=t),s("Looking for similar text: "+l);const d=()=>{for(const e of je(n)){if(i.has(e))continue;i.add(e);const{innerText:n}=ke(e),o=Ct(f,n.length-c+1);for(let i=0;ip.disconnect()));p.observe(document,{childList:!0,characterData:!0,subtree:!0}),d()},"hide-if-contains-visible-text":function(e,t,n=null,...r){let o=ke([]);const i=new Lt([["-snippet-box-margin","2"]]);for(let e of r){e=ke(e);let t=e.indexOf(":");if(t<0)continue;let n=e.slice(0,t).trim().toString(),r=e.slice(t+1).trim().toString();n&&r&&(i.has(n)?i.set(n,r):o.push([n,r]))}let s=ke([["opacity","0"],["font-size","0px"],["color","rgba(0, 0, 0, 0)"]]),l=new Lt(s.concat(o));function a(e,t){t||(t=Nt(e)),t=ke(t);for(const[e,n]of l){if(nt(n).test(t.getPropertyValue(e)))return!1}let n=t.getPropertyValue("color");return t.getPropertyValue("background-color")!=n}function c(e,t){let n=Nt(e,t);if(!qe(e,n)||!a(e,n))return"";let{content:r}=ke(n);if(r&&"none"!==r){let t=ke([]);return r=ke(r).trim().replace(/(["'])(?:(?=(\\?))\2.)*?\1/g,(e=>""+(t.push(ke(e).slice(1,-1))-1))),r=r.replace(/\s*attr\(\s*([^\s,)]+)[^)]*?\)\s*/g,((t,n)=>ke(e).getAttribute(n)||"")),r.replace(/\x01(\d+)/g,((e,n)=>t[n]))}return""}function u(e,t,{boxMargin:n=2}={}){const r=ke(e).getBoundingClientRect(),o=ke(t).getBoundingClientRect(),i=o.left-n,s=o.right+n,l=o.top-n,a=o.bottom+n;return i<=r.left&&r.left<=s&&l<=r.top&&r.top<=a&&l<=r.bottom&&r.bottom<=a&&i<=r.right&&r.right<=s}function f(e,t,n,r,{boxMargin:o=2}={}){let i=!n;if(i&&(n=Nt(e)),!qe(e,n,i&&t))return"";r||"hidden"!==ke(n).getPropertyValue("overflow-x")&&"hidden"!==ke(n).getPropertyValue("overflow-y")||(r=e);let s=c(e,":before");for(let t of ke(e).childNodes)switch(ke(t).nodeType){case Vt:s+=f(t,e,Nt(t),r,{boxMargin:o});break;case It:r?u(e,r,{boxMargin:o})&&a(e,n)&&(s+=ke(t).nodeValue):a(e,n)&&(s+=ke(t).nodeValue)}return s+c(e,":after")}const d=i.get("-snippet-box-margin"),p=Rt(d)||0;let h=nt(e),w=new At;const g=Xe(((e,t)=>{if(w.has(e))return!1;w.add(e);let n=f(e,t,null,null,{boxMargin:p}),r=h.test(n);return ot()&&n.length&<(r,h,n),r}),t,n);g.race(wt("hide-if-contains-visible-text",(()=>{g.disconnect()})))},"hide-if-contains-and-matches-style":function(e,t="*",n=null,r=null,o=null){null==n&&(n=t);let i=nt(e),s=r?nt(r):null,l=o?nt(o):null,a=()=>{for(let e of je(n))if(i.test(ke(e).textContent)&&(!l||l.test(Je(e)))){let n=ke(e).closest(t);!n||s&&!s.test(Je(n))||(u(),Fe(n))}},c=new gt(a),u=wt("hide-if-contains-and-matches-style",(()=>c.disconnect()));c.observe(document,{childList:!0,characterData:!0,subtree:!0}),a()},"hide-if-has-and-matches-style":function(e,t="*",n=null,r=null,o=null){null==n&&(n=t);let i=r?nt(r):null,s=o?nt(o):null,l=()=>{for(let r of je(n))if(ke(r).querySelector(e)&&(!s||s.test(Je(r)))){let e=ke(r).closest(t);!e||i&&!i.test(Je(e))||(c(),Fe(e))}},a=new jt(l),c=wt("hide-if-has-and-matches-style",(()=>a.disconnect()));a.observe(document,{childList:!0,subtree:!0}),l()},"hide-if-labelled-by":function(e,t,n=null){let r=null==n,o=nt(e),i=new _t,s=()=>{for(let e of je(t)){let t=r?e:ke(e).closest(n);if(!t||!qe(e,Ht(e),t))continue;let s=ke(e).getAttribute("aria-labelledby"),l=()=>{i.has(t)||o.test(ke(e).getAttribute("aria-label")||"")&&(a(),i.add(t),Fe(t))};if(s)for(let e of ke(s).split(/\s+/)){let n=ke(document).getElementById(e);n?!i.has(n)&&o.test(n.innerText)&&(a(),i.add(n),Fe(t)):l()}else l()}},l=new $t(s),a=wt("hide-if-labelled-by",(()=>l.disconnect()));l.observe(document,{characterData:!0,childList:!0,subtree:!0}),s()},"hide-if-contains-image":function(e,t,n){null==n&&(n=t);let r=nt(e),o=()=>{for(let e of je(n)){let n=yt(e),o=ke(n["background-image"]).match(/^url\("(.*)"\)$/);o&&Tt(o[1]).then((n=>{if(r.test(new xt(n).reduce(((e,t)=>e+function(e,t=2){let n=ke(e).toString(16);n.lengthi.disconnect()));i.observe(document,{childList:!0,subtree:!0}),o()},"simulate-event-poc":function(e,t,n="0"){if(!e)throw new Ke("[simulate-event snippet]: No event type provided.");if(!t)throw new Ke("[simulate-event snippet]: No selector provided.");let r=ze(t),o=Ue(n,10),i=new Qe;function s(){r((t=>{i.has(t)||(i.add(t),Ge((()=>{ke(t).dispatchEvent(new Ye(e,{bubbles:!0,cancelable:!0}))}),o))}))}new Ze(s).observe(document,{childList:!0,subtree:!0}),s()}}; ++const snippets=Xt; ++let context; ++for (const [name, ...args] of filters) { ++if (snippets.hasOwnProperty(name)) { ++try { context = snippets[name].apply(context, args); } ++catch (error) { console.error(error); } ++} ++} ++context = void 0; ++})(e, ...t); ++ ++const callback = (environment, ...filters) => { ++const e=Proxy,{apply:t,bind:r,call:n}=Function,o=n.bind(t),i=n.bind(r),s=n.bind(n),a={get:(e,t)=>i(n,e[t])},l=t=>new e(t,a),c=(t,r)=>new e(t,{apply:(e,t,n)=>o(r,t,n)}),u={get:(e,t)=>i(e[t],e)},f=t=>new e(t,u),{assign:p,defineProperties:d,freeze:h,getOwnPropertyDescriptor:w,getOwnPropertyDescriptors:g,getPrototypeOf:y}=f(Object),{hasOwnProperty:m}=l({}),{species:b}=Symbol,v={get(e,t){const r=e[t];class n extends r{}const o=g(r.prototype);delete o.constructor,h(d(n.prototype,o));const i=g(r);return delete i.length,delete i.prototype,i[b]={value:n},h(d(n,i))}},E=t=>new e(t,v),S="undefined"!=typeof environment?environment:{};"undefined"==typeof globalThis&&(window.globalThis=window);const{apply:M,ownKeys:T}=f(Reflect),x="world"in S,O=x&&"ISOLATED"===S.world,P=x&&"MAIN"===S.world,j="object"==typeof chrome&&!!chrome.runtime,N="object"==typeof browser&&!!browser.runtime,L=!P&&(O||j||N),k=e=>L?e:C(e,H(e)),{create:C,defineProperties:A,defineProperty:W,freeze:D,getOwnPropertyDescriptor:$,getOwnPropertyDescriptors:H}=f(Object),z=f(globalThis),R=L?globalThis:E(globalThis),{Map:F,RegExp:I,Set:J,WeakMap:V,WeakSet:B}=R,U=(e,t,r=null)=>{const n=T(t);for(const o of T(e)){if(n.includes(o))continue;const i=$(e,o);if(r&&"value"in i){const{value:e}=i;"function"==typeof e&&(i.value=r(e))}W(t,o,i)}},_=e=>{const t=R[e];class r extends t{}const{toString:n,valueOf:o}=t.prototype;A(r.prototype,{toString:{value:n},valueOf:{value:o}});const i=e.toLowerCase(),s=e=>function(){const t=M(e,this,arguments);return typeof t===i?new r(t):t};return U(t,r,s),U(t.prototype,r.prototype,s),r},X=D({frozen:new V,hidden:new B,iframePropertiesToAbort:{read:new J,write:new J},abortedIframes:new V}),G=new I("^[A-Z]");var q=new Proxy(new F([["chrome",L&&(j&&chrome||N&&browser)||void 0],["isExtensionContext",L],["variables",X],["console",k(console)],["document",globalThis.document],["performance",k(performance)],["JSON",k(JSON)],["Map",F],["Math",k(Math)],["Number",L?Number:_("Number")],["RegExp",I],["Set",J],["String",L?String:_("String")],["WeakMap",V],["WeakSet",B],["MouseEvent",MouseEvent]]),{get(e,t){if(e.has(t))return e.get(t);let r=globalThis[t];return"function"==typeof r&&(r=(G.test(t)?R:z)[t]),e.set(t,r),r},has:(e,t)=>e.has(t)});const K={WeakSet:WeakSet,WeakMap:WeakMap,WeakValue:class{has(){return!1}set(){}}},{apply:Y}=Reflect;const{Map:Z,WeakMap:Q,WeakSet:ee,setTimeout:te}=q;let re=!0,ne=e=>{e.clear(),re=!re};var oe=function(e){const{WeakSet:t,WeakMap:r,WeakValue:n}=this||K,o=new t,i=new r,s=new n;return function(t){if(o.has(t))return t;if(i.has(t))return i.get(t);if(s.has(t))return s.get(t);const r=Y(e,this,arguments);return o.add(r),r!==t&&("object"==typeof t&&t?i:s).set(t,r),r}}.bind({WeakMap:Q,WeakSet:ee,WeakValue:class extends Z{set(e,t){return re&&(re=!re,te(ne,0,this)),super.set(e,t)}}});const{concat:ie,includes:se,join:ae,reduce:le,unshift:ce}=l([]),ue=E(globalThis),{Map:fe,WeakMap:pe}=ue,de=new fe,he=t=>{const r=(e=>{const t=[];let r=e;for(;r;){if(de.has(r))ce(t,de.get(r));else{const e=g(r);de.set(r,e),ce(t,e)}r=y(r)}return ce(t,{}),o(p,null,t)})("function"==typeof t?t.prototype:t),n={get(e,t){if(t in r){const{value:n,get:o}=r[t];if(o)return s(o,e);if("function"==typeof n)return i(n,e)}return e[t]},set(e,t,n){if(t in r){const{set:o}=r[t];if(o)return s(o,e,n),!0}return e[t]=n,!0}};return t=>new e(t,n)},{isExtensionContext:we,Array:ge,Number:ye,String:me,Object:be}=q,{isArray:ve}=ge,{getOwnPropertyDescriptor:Ee,setPrototypeOf:Se}=be,{toString:Me}=be.prototype,{slice:Te}=me.prototype,{get:xe}=Ee(Node.prototype,"nodeType"),Oe=we?{}:{Attr:he(Attr),CanvasRenderingContext2D:he(CanvasRenderingContext2D),CSSStyleDeclaration:he(CSSStyleDeclaration),Document:he(Document),Element:he(Element),HTMLCanvasElement:he(HTMLCanvasElement),HTMLElement:he(HTMLElement),HTMLImageElement:he(HTMLImageElement),HTMLScriptElement:he(HTMLScriptElement),MutationRecord:he(MutationRecord),Node:he(Node),ShadowRoot:he(ShadowRoot),get CSS2Properties(){return Oe.CSSStyleDeclaration}},Pe=(e,t)=>{if("Element"!==t&&t in Oe)return Oe[t](e);if(ve(e))return Se(e,ge.prototype);const r=(e=>s(Te,s(Me,e),8,-1))(e);if(r in Oe)return Oe[r](e);if(r in q)return Se(e,q[r].prototype);if("nodeType"in e)switch(s(xe,e)){case 1:if(!(t in Oe))throw new Error("unknown hint "+t);return Oe[t](e);case 2:return Oe.Attr(e);case 3:return Oe.Node(e);case 9:return Oe.Document(e)}throw new Error("unknown brand "+r)};var je=we?e=>e===window||e===globalThis?q:e:oe(((e,t="Element")=>{if(e===window||e===globalThis)return q;switch(typeof e){case"object":return e&&Pe(e,t);case"string":return new me(e);case"number":return new ye(e);default:throw new Error("unsupported value")}}));const Ne={get(e,t){const r=e;for(;!m(e,t);)e=y(e);const{get:n,set:i}=w(e,t);return function(){return arguments.length?o(i,r,arguments):s(n,r)}}},Le=t=>new e(t,Ne);let ke=!1;function Ce(){return ke}const{console:Ae}=je(window),We=()=>{};function De(...e){Ce()&&je(e).unshift("%c DEBUG","font-weight: bold"),Ae.log(...e)}function $e(e){return i(Ce()?De:We,null,e)}let{Math:He,RegExp:ze}=je(window);function Re(e){let{length:t}=e;if(t>1&&"/"===e[0]){let r="/"===e[t-1];if(r||t>2&&je(e).endsWith("/i")){let t=[je(e).slice(1,r?-1:-2)];return r||t.push("i"),new ze(...t)}}return new ze(je(e).replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))}function Fe(){return je(He.floor(2116316160*He.random()+60466176)).toString(36)}let{parseFloat:Ie,variables:Je,Array:Ve,Error:Be,Map:Ue,Object:_e,ReferenceError:Xe,Set:Ge,WeakMap:qe}=je(window),{onerror:Ke}=Le(window),Ye=Node.prototype,Ze=Element.prototype,Qe=null;function et(e,t,r){let n=je(t),o=n.indexOf(".");if(-1==o){let n=_e.getOwnPropertyDescriptor(e,t);if(n&&!n.configurable)return;let o=_e.assign({},r,{configurable:!0});if(!n&&!o.get&&o.set){let r=e[t];o.get=()=>r}return void _e.defineProperty(e,t,o)}let i=n.slice(0,o).toString();t=n.slice(o+1).toString();let s=e[i];!s||"object"!=typeof s&&"function"!=typeof s||et(s,t,r);let a=_e.getOwnPropertyDescriptor(e,i);if(a&&!a.configurable)return;Qe||(Qe=new qe),Qe.has(e)||Qe.set(e,new Ue);let l=Qe.get(e);if(l.has(i))return void l.get(i).set(t,r);let c=new Ue([[t,r]]);l.set(i,c),_e.defineProperty(e,i,{get:()=>s,set(e){if(s=e,s&&("object"==typeof s||"function"==typeof s))for(let[e,t]of c)et(s,e,t)},configurable:!0})}function tt(e){let t=Ke();Ke(((...r)=>{let n=r.length&&r[0];return!("string"!=typeof n||!je(n).includes(e))||("function"==typeof t?o(t,this,r):void 0)}))}function rt(e,t,r){let n=$e(e);if(!r)return void n("no property to abort on read");let o=Fe();n(`aborting on ${r} access`),et(t,r,{get:function(){throw n(`${r} access aborted`),new Xe(o)},set(){}}),tt(o)}function nt(e,t,r){let n=$e(e);if(!r)return void n("no property to abort on write");let o=Fe();n(`aborting when setting ${r}`),et(t,r,{set:function(){throw n(`setting ${r} aborted`),new Xe(o)}}),tt(o)}function ot(e,t=!1,r=!1){let n=Je.abortedIframes,i=Je.iframePropertiesToAbort;for(let o of Ve.from(window.frames))if(n.has(o))for(let i of e)t&&n.get(o).read.add(i),r&&n.get(o).write.add(i);for(let n of e)t&&i.read.add(n),r&&i.write.add(n);function a(){for(let e of Ve.from(window.frames)){n.has(e)||n.set(e,{read:new Ge(i.read),write:new Ge(i.write)});let t=n.get(e).read;if(t.size>0){let r=Ve.from(t);t.clear();for(let t of r)rt("abort-on-iframe-property-read",e,t)}let r=n.get(e).write;if(r.size>0){let t=Ve.from(r);r.clear();for(let r of t)nt("abort-on-iframe-property-write",e,r)}}}a(),n.has(document)||(n.set(document,!0),function(e){let t;function r(e,t){for(let r of t){et(e,r,n(e,r))}}function n(t,r){let n=t[r];return{get:()=>function(...t){let r;return r=o(n,this,t),e&&e(),r}}}function i(t,r){let n=_e.getOwnPropertyDescriptor(t,r),{set:o}=n||{};return{set(t){let r;return r=s(o,this,t),e&&e(),r}}}r(Ye,["appendChild","insertBefore","replaceChild"]),r(Ze,["append","prepend","replaceWith","after","before","insertAdjacentElement","insertAdjacentHTML"]),t=i(Ze,"innerHTML"),et(Ze,"innerHTML",t),t=i(Ze,"outerHTML"),et(Ze,"outerHTML",t)}(a))}let{Object:it}=window;function st(e,t){if(!(e instanceof it))return;let r=e,n=je(t).split(".");if(0===n.length)return;for(let e=0;e{};case"trueFunc":return()=>!0;case"falseFunc":return()=>!1;case"emptyArray":return[];case"emptyObj":return{};case"undefined":return;case"":return e;default:if(at.test(e))return Ie(e);throw new Be(`[override-property-read snippet]: Value "${e}" is not valid.`)}}let{HTMLScriptElement:ct,Object:ut,ReferenceError:ft}=je(window),pt=ut.getPrototypeOf(ct);let{Error:dt}=je(window),{cookie:ht}=Le(document);let{document:wt,getComputedStyle:gt,isExtensionContext:yt,variables:mt,Array:bt,MutationObserver:vt,Object:Et,XPathEvaluator:St,XPathExpression:Mt,XPathResult:Tt}=je(window),{querySelectorAll:xt}=wt,Ot=xt&&i(xt,wt);const{assign:Pt,setPrototypeOf:jt}=Et;class Nt extends Mt{evaluate(...e){return jt(o(super.evaluate,this,e),Tt.prototype)}}class Lt extends St{createExpression(...e){return jt(o(super.createExpression,this,e),Nt.prototype)}}function kt(e){if(mt.hidden.has(e))return;!function(e){yt&&"function"==typeof checkElement&&checkElement(e)}(e),mt.hidden.add(e);let{style:t}=je(e),r=je(t,"CSSStyleDeclaration"),n=je([]),{debugCSSProperties:o}=S;for(let[e,t]of o||[["display","none"]])r.setProperty(e,t,"important"),n.push([e,r.getPropertyValue(e)]);new vt((()=>{for(let[e,t]of n){let n=r.getPropertyValue(e),o=r.getPropertyPriority(e);n==t&&"important"==o||r.setProperty(e,t,"important")}})).observe(e,{attributes:!0,attributeFilter:["style"]})}function Ct(e){let t=e;if(t.startsWith("xpath(")&&t.endsWith(")")){let t=function(e){let t=e;if(t.startsWith("xpath(")&&t.endsWith(")")){let e=t.slice(6,-1),r=(new Lt).createExpression(e,null),n=Tt.ORDERED_NODE_SNAPSHOT_TYPE;return e=>{if(!e)return;let t=r.evaluate(wt,n,null),{snapshotLength:o}=t;for(let r=0;rOt(e).forEach(t)}(e);return()=>{let e=je([]);return t((t=>e.push(t))),e}}return()=>bt.from(Ot(e))}let{ELEMENT_NODE:At,TEXT_NODE:Wt,prototype:Dt}=Node,{prototype:$t}=Element,{prototype:Ht}=HTMLElement,{console:zt,variables:Rt,DOMParser:Ft,Error:It,MutationObserver:Jt,Object:Vt,ReferenceError:Bt}=je(window),{getOwnPropertyDescriptor:Ut}=Vt;je(window);const{Map:_t,MutationObserver:Xt,Object:Gt,Set:qt,WeakSet:Kt}=je(window);let Yt=Element.prototype,{attachShadow:Zt}=Yt,Qt=new Kt,er=new _t,tr=null;const{Error:rr,JSON:nr,Map:or,Object:ir}=je(window);let sr=null;let{Error:ar,JSON:lr,Map:cr,Object:ur}=je(window),fr=null;let{Error:pr}=je(window);let{Error:dr,Map:hr,Object:wr,console:gr}=je(window),{toString:yr}=Function.prototype,mr=EventTarget.prototype,{addEventListener:br}=mr,vr=null;let Er,{URL:Sr,fetch:Mr}=je(window),{delete:Tr}=l(URLSearchParams.prototype);const xr={"abort-current-inline-script":function(e,t=null){let r=t?Re(t):null,n=Fe(),o=je(document).currentScript,i=window,a=je(e).split("."),l=je(a).pop();for(let e of je(a))if(i=i[e],!i||"object"!=typeof i&&"function"!=typeof i)return;let{get:c,set:u}=ut.getOwnPropertyDescriptor(i,l)||{},f=i[l],p=()=>{let e=je(document).currentScript;if(e instanceof pt&&""==je(e,"HTMLScriptElement").src&&e!=o&&(!r||r.test(je(e).textContent)))throw new ft(n)};et(i,l,{get(){return p(),c?s(c,this):f},set(e){p(),u?s(u,this,e):f=e}}),tt(n)},"abort-on-iframe-property-read":function(...e){ot(e,!0,!1)},"abort-on-iframe-property-write":function(...e){ot(e,!1,!0)},"abort-on-property-read":function(e){rt("abort-on-property-read",window,e)},"abort-on-property-write":function(e){nt("abort-on-property-write",window,e)},"cookie-remover":function(e){if(!e)throw new dt("[cookie-remover snippet]: No cookie to remove.");let t=$e("cookie-remover"),r=Re(e);if(je(/^http|^about/).test(location.protocol)){t("Parsing cookies for matches");for(const e of je(je(ht()).split(";").filter((e=>r.test(je(e).split("=")[0]))))){let r=je(location.hostname),n=je(e).split("=")[0],o="expires=Thu, 01 Jan 1970 00:00:00 GMT",i="path=/",s="domain="+r.slice(r.indexOf(".")+1);ht(`${je(n).trim()}=;${o};${i};${s}`),t(`Set expiration date on ${n}`)}}else t("Snippet only works for http or https and about.")},debug:function(){ke=!0},"freeze-element":function(e,t="",...r){let n,i,a=!1,l=!1,c=je(r).filter((e=>!h(e))),u=je(r).filter((e=>h(e))).map(Re),f=Fe(),p=Ct(e);!function(){let r=je(t).split("+");1===r.length&&""===r[0]&&(r=[]);for(let t of r)switch(t){case"subtree":a=!0;break;case"abort":l=!0;break;default:throw new It("[freeze] Unknown option passed to the snippet. [selector]: "+e+" [option]: "+t)}}();let d={selector:e,shouldAbort:l,rid:f,exceptionSelectors:c,regexExceptions:u,changeId:0};function h(e){return e.length>=2&&"/"==e[0]&&"/"==e[e.length-1]}function w(){i=p(),g(i,!1)}function g(e,t=!0){for(let r of e)Rt.frozen.has(r)||(Rt.frozen.set(r,d),!t&&a&&new Jt((e=>{for(let t of je(e))g(je(t,"MutationRecord").addedNodes)})).observe(r,{childList:!0,subtree:!0}),a&&je(r).nodeType===At&&g(je(r).childNodes))}function y(e,...t){De(`[freeze][${e}] `,...t)}function m(e,t,r,n){let o=n.selector,i=n.changeId,s="string"==typeof e,a=n.shouldAbort?"aborting":"watching";switch(zt.groupCollapsed(`[freeze][${i}] ${a}: ${o}`),r){case"appendChild":case"append":case"prepend":case"insertBefore":case"replaceChild":case"insertAdjacentElement":case"insertAdjacentHTML":case"insertAdjacentText":case"innerHTML":case"outerHTML":y(i,s?"text: ":"node: ",e),y(i,"added to node: ",t);break;case"replaceWith":case"after":case"before":y(i,s?"text: ":"node: ",e),y(i,"added to node: ",je(t).parentNode);break;case"textContent":case"innerText":case"nodeValue":y(i,"content of node: ",t),y(i,"changed to: ",e)}y(i,`using the function "${r}"`),zt.groupEnd(),n.changeId++}function b(e,t){if(t)for(let r of t)if(r.test(e))return!0;return!1}function v(e){throw new Bt(e)}function E(e,t,r,n){let o=new Ft,{body:i}=je(o.parseFromString(e,"text/html")),s=S(je(i).childNodes,t,r,n);return je(s).map((e=>{switch(je(e).nodeType){case At:return je(e).outerHTML;case Wt:return je(e).textContent;default:return""}})).join("")}function S(e,t,r,n){let o=je([]);for(let i of e)M(i,t,r,n)&&o.push(i);return o}function M(e,t,r,n){let o=n.shouldAbort,i=n.regexExceptions,s=n.exceptionSelectors,a=n.rid;if("string"==typeof e){let s=e;return!!b(s,i)||(Ce()&&m(s,t,r,n),o&&v(a),Ce())}let l=e;switch(je(l).nodeType){case At:return!!function(e,t){if(t){let r=je(e);for(let e of t)if(r.matches(e))return!0}return!1}(l,s)||(o&&(Ce()&&m(l,t,r,n),v(a)),!!Ce()&&(kt(l),m(l,t,r,n),!0));case Wt:return!!b(je(l).textContent,i)||(Ce()&&m(l,t,r,n),o&&v(a),!1);default:return!0}}function T(e,t,r,n){let i=Ut(e,t)||{},a=i.get&&s(i.get,e)||i.value;if(a)return{get:()=>function(...e){if(r(this)){let r=n(this);if(r){let n=e[0];if(!M(n,this,t,r))return n}}return o(a,this,e)}}}function x(e,t,r,n){let i=Ut(e,t)||{},a=i.get&&s(i.get,e)||i.value;if(a)return{get:()=>function(...e){if(!r(this))return o(a,this,e);let i=n(this);if(!i)return o(a,this,e);let s=S(e,this,t,i);return s.length>0?o(a,this,s):void 0}}}function O(e,t,r,n){let i=Ut(e,t)||{},a=i.get&&s(i.get,e)||i.value;if(a)return{get:()=>function(...e){let[i,l]=e,c="afterbegin"===i||"beforeend"===i;if(r(this,c)){let e=n(this,c);if(e){let r,n=c?this:je(this).parentNode;switch(t){case"insertAdjacentElement":if(!M(l,n,t,e))return l;break;case"insertAdjacentHTML":return r=E(l,n,t,e),r?s(a,this,i,r):void 0;case"insertAdjacentText":if(!M(l,n,t,e))return}}}return o(a,this,e)}}}function P(e,t,r,n){let o=Ut(e,t)||{},{set:i}=o;if(i)return{set(e){if(!r(this))return s(i,this,e);let o=n(this);if(!o)return s(i,this,e);let a=E(e,this,t,o);return a?s(i,this,a):void 0}}}function j(e,t,r,n){let o=Ut(e,t)||{},{set:i}=o;if(i)return{set(e){if(!r(this))return s(i,this,e);let o=n(this);return o?M(e,this,t,o)?s(i,this,e):void 0:s(i,this,e)}}}Rt.frozen.has(document)||(Rt.frozen.set(document,!0),function(){let e;function t(e){return e&&Rt.frozen.has(e)}function r(e){try{return e&&(Rt.frozen.has(e)||Rt.frozen.has(je(e).parentNode))}catch(e){return!1}}function n(e,t){try{return e&&(Rt.frozen.has(e)&&t||Rt.frozen.has(je(e).parentNode)&&!t)}catch(e){return!1}}function o(e){return Rt.frozen.get(e)}function i(e){try{if(Rt.frozen.has(e))return Rt.frozen.get(e);let t=je(e).parentNode;return Rt.frozen.get(t)}catch(e){}}function s(e,t){try{if(Rt.frozen.has(e)&&t)return Rt.frozen.get(e);let r=je(e).parentNode;return Rt.frozen.get(r)}catch(e){}}e=T(Dt,"appendChild",t,o),et(Dt,"appendChild",e),e=T(Dt,"insertBefore",t,o),et(Dt,"insertBefore",e),e=T(Dt,"replaceChild",t,o),et(Dt,"replaceChild",e),e=x($t,"append",t,o),et($t,"append",e),e=x($t,"prepend",t,o),et($t,"prepend",e),e=x($t,"replaceWith",r,i),et($t,"replaceWith",e),e=x($t,"after",r,i),et($t,"after",e),e=x($t,"before",r,i),et($t,"before",e),e=O($t,"insertAdjacentElement",n,s),et($t,"insertAdjacentElement",e),e=O($t,"insertAdjacentHTML",n,s),et($t,"insertAdjacentHTML",e),e=O($t,"insertAdjacentText",n,s),et($t,"insertAdjacentText",e),e=P($t,"innerHTML",t,o),et($t,"innerHTML",e),e=P($t,"outerHTML",r,i),et($t,"outerHTML",e),e=j(Dt,"textContent",t,o),et(Dt,"textContent",e),e=j(Ht,"innerText",t,o),et(Ht,"innerText",e),e=j(Dt,"nodeValue",t,o),et(Dt,"nodeValue",e)}()),n=new Jt(w),n.observe(document,{childList:!0,subtree:!0}),w()},"hide-if-shadow-contains":function(e,t="*"){let r=`${e}\\${t}`;er.has(r)||er.set(r,[Re(e),t,We]),tr||(tr=new Xt((e=>{let t=new qt;for(let{target:r}of je(e)){let e=je(r).parentNode;for(;e;)[r,e]=[e,je(r).parentNode];if(!Qt.has(r)&&!t.has(r)){t.add(r);for(let[e,t,n]of er.values())if(e.test(je(r).textContent)){let e=je(r.host).closest(t);e&&(n(),je(r).appendChild(document.createElement("style")).textContent=":host {display: none !important}",kt(e),Qt.add(r))}}}})),Gt.defineProperty(Yt,"attachShadow",{value:c(Zt,(function(){let e=o(Zt,this,arguments);return tr.observe(e,{childList:!0,characterData:!0,subtree:!0}),e}))}))},"json-override":function(e,t,r="",n=""){if(!e)throw new rr("[json-override snippet]: Missing paths to override.");if(void 0===t)throw new rr("[json-override snippet]: No value to override with.");if(!sr){let e=$e("json-override"),{parse:t}=nr;sr=new or,ir.defineProperty(window.JSON,"parse",{value:c(t,(function(r){let n=o(t,this,arguments);for(let{prune:t,needle:o,filter:i,value:s}of sr.values())if(!i||i.test(r)){if(je(o).some((e=>!st(n,e))))return n;for(let r of t){let t=st(n,r);void 0!==t&&(e(`Found ${r} replaced it with ${s}`),t[0][t[1]]=lt(s))}}return n}))}),e("Wrapped JSON.parse for override")}sr.set(e,{prune:je(e).split(/ +/),needle:r.length?je(r).split(/ +/):[],filter:n?Re(n):null,value:t})},"json-prune":function(e,t=""){if(!e)throw new ar("Missing paths to prune");if(!fr){let e=$e("json-prune"),{parse:t}=lr;fr=new cr,ur.defineProperty(window.JSON,"parse",{value:c(t,(function(){let r=o(t,this,arguments);for(let{prune:t,needle:n}of fr.values()){if(je(n).some((e=>!st(r,e))))return r;for(let n of t){let t=st(r,n);void 0!==t&&(e(`Found ${n} and deleted`),delete t[0][t[1]])}}return r}))}),e("Wrapped JSON.parse for prune")}fr.set(e,{prune:je(e).split(/ +/),needle:t.length?je(t).split(/ +/):[]})},"override-property-read":function(e,t){if(!e)throw new pr("[override-property-read snippet]: No property to override.");if(void 0===t)throw new pr("[override-property-read snippet]: No value to override with.");let r=$e("override-property-read"),n=lt(t);r(`Overriding ${e}.`),et(window,e,{get:()=>(r(`${e} override done.`),n),set(){}})},"prevent-listener":function(e,t,r){if(!e)throw new dr("[prevent-listener snippet]: No event type.");if(!vr){vr=new hr;let e=$e("[prevent]");wr.defineProperty(mr,"addEventListener",{value:c(br,(function(t,r){for(let{evt:n,handlers:o,selectors:i}of vr.values()){if(!n.test(t))continue;let a=this instanceof Element;for(let l=0;lc.test(s(yr,"function"==typeof r?r:r.handleEvent));if((!c||f())&&(!u||a&&je(this).matches(u)))return void(Ce()&&(gr.groupCollapsed("DEBUG [prevent] was successful"),e(`type: ${t} matching ${n}`),e("handler:",r),c&&e(`matching ${c}`),u&&e("on element: ",this,` matching ${u}`),e("was prevented from being added"),gr.groupEnd()))}}return o(br,this,arguments)}))}),e("Wrapped addEventListener")}vr.has(e)||vr.set(e,{evt:Re(e),handlers:[],selectors:[]});let{handlers:n,selectors:i}=vr.get(e);n.push(t?Re(t):null),i.push(r)},"strip-fetch-query-parameter":function(e,t=null){Er||(Er=new Map,window.fetch=c(Mr,((...e)=>{let[t]=e;if("string"==typeof t){let r=new Sr(t);for(let[n,o]of Er)o&&!o.test(t)||(Tr(r.searchParams,n),e[0]=r.href)}return o(Mr,self,e)}))),Er.set(e,t&&Re(t))},trace:function(...e){o(De,null,e)}}; ++const snippets=xr; ++let context; ++for (const [name, ...args] of filters) { ++if (snippets.hasOwnProperty(name)) { ++try { context = snippets[name].apply(context, args); } ++catch (error) { console.error(error); } ++} ++} ++context = void 0; ++}; ++const graph = new Map([["abort-current-inline-script",null],["abort-on-iframe-property-read",null],["abort-on-iframe-property-write",null],["abort-on-property-read",null],["abort-on-property-write",null],["cookie-remover",null],["debug",null],["freeze-element",null],["hide-if-shadow-contains",null],["json-override",null],["json-prune",null],["override-property-read",null],["prevent-listener",null],["strip-fetch-query-parameter",null],["trace",null]]); ++callback.get = snippet => graph.get(snippet); ++callback.has = snippet => graph.has(snippet); ++ ++ if (t.every(([name]) => !callback.has(name))) return; ++ const append = () => { ++ URL.revokeObjectURL( ++ Object.assign( ++ document.documentElement.appendChild(document.createElement("script")), ++ {async: false, src: URL.createObjectURL(new Blob([ ++ "(" + callback + ")(..." + JSON.stringify([e, ...t]) + ")" ++ ]))} ++ ).src ++ ); ++ }; ++ try { append(); } ++ catch (_) { ++ document.addEventListener("readystatechange", append, {once:true}); ++ } ++} +\ No newline at end of file +diff --git a/components/resources/adblocking/snippets/dist/isolated-first.source.jst b/components/resources/adblocking/snippets/dist/isolated-first.source.jst +new file mode 100755 +--- /dev/null ++++ b/components/resources/adblocking/snippets/dist/isolated-first.source.jst +@@ -0,0 +1,3126 @@ ++(e, ...t) => { ++/*! ++ * This file is part of eyeo's Anti-Circumvention Snippets module (@eyeo/snippets), ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * @eyeo/snippets 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/snippets 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/snippets. If not, see . ++ */ ++ ((environment, ...filters) => { ++ /*! ++ * This file is part of eyeo's Anti-Circumvention Snippets module (@eyeo/snippets), ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * @eyeo/snippets 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/snippets 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/snippets. If not, see . ++ */ ++ const $$1 = Proxy; ++ ++ const {apply: a, bind: b, call: c} = Function; ++ const apply$2 = c.bind(a); ++ const bind = c.bind(b); ++ const call = c.bind(c); ++ ++ const callerHandler = { ++ get(target, name) { ++ return bind(c, target[name]); ++ } ++ }; ++ ++ const caller = target => new $$1(target, callerHandler); ++ ++ const handler$1 = { ++ get(target, name) { ++ return bind(target[name], target); ++ } ++ }; ++ ++ const bound = target => new $$1(target, handler$1); ++ ++ const { ++ assign: assign$1, ++ defineProperties: defineProperties$1, ++ freeze: freeze$1, ++ getOwnPropertyDescriptor: getOwnPropertyDescriptor$2, ++ getOwnPropertyDescriptors: getOwnPropertyDescriptors$1, ++ getPrototypeOf ++ } = bound(Object); ++ ++ caller({}); ++ ++ const {species} = Symbol; ++ ++ const handler = { ++ get(target, name) { ++ const Native = target[name]; ++ class Secure extends Native {} ++ ++ const proto = getOwnPropertyDescriptors$1(Native.prototype); ++ delete proto.constructor; ++ freeze$1(defineProperties$1(Secure.prototype, proto)); ++ ++ const statics = getOwnPropertyDescriptors$1(Native); ++ delete statics.length; ++ delete statics.prototype; ++ statics[species] = {value: Secure}; ++ return freeze$1(defineProperties$1(Secure, statics)); ++ } ++ }; ++ ++ const secure = target => new $$1(target, handler); ++ ++ const libEnvironment = typeof environment !== "undefined" ? environment : ++ {}; ++ ++ if (typeof globalThis === "undefined") ++ window.globalThis = window; ++ ++ const {apply: apply$1, ownKeys} = bound(Reflect); ++ ++ const worldEnvDefined = "world" in libEnvironment; ++ const isIsolatedWorld = worldEnvDefined && libEnvironment.world === "ISOLATED"; ++ const isMainWorld = worldEnvDefined && libEnvironment.world === "MAIN"; ++ const isChrome = typeof chrome === "object" && !!chrome.runtime; ++ const isOtherThanChrome = typeof browser === "object" && !!browser.runtime; ++ const isExtensionContext$2 = !isMainWorld && ++ (isIsolatedWorld || isChrome || isOtherThanChrome); ++ const copyIfExtension = value => isExtensionContext$2 ? ++ value : ++ create(value, getOwnPropertyDescriptors(value)); ++ ++ const { ++ create, ++ defineProperties, ++ defineProperty, ++ freeze, ++ getOwnPropertyDescriptor: getOwnPropertyDescriptor$1, ++ getOwnPropertyDescriptors ++ } = bound(Object); ++ ++ const invokes = bound(globalThis); ++ const classes = isExtensionContext$2 ? globalThis : secure(globalThis); ++ const {Map: Map$5, RegExp: RegExp$1, Set, WeakMap: WeakMap$3, WeakSet: WeakSet$6} = classes; ++ ++ const augment = (source, target, method = null) => { ++ const known = ownKeys(target); ++ for (const key of ownKeys(source)) { ++ if (known.includes(key)) ++ continue; ++ ++ const descriptor = getOwnPropertyDescriptor$1(source, key); ++ if (method && "value" in descriptor) { ++ const {value} = descriptor; ++ if (typeof value === "function") ++ descriptor.value = method(value); ++ } ++ defineProperty(target, key, descriptor); ++ } ++ }; ++ ++ const primitive = name => { ++ const Super = classes[name]; ++ class Class extends Super {} ++ const {toString, valueOf} = Super.prototype; ++ defineProperties(Class.prototype, { ++ toString: {value: toString}, ++ valueOf: {value: valueOf} ++ }); ++ const type = name.toLowerCase(); ++ const method = callback => function() { ++ const result = apply$1(callback, this, arguments); ++ return typeof result === type ? new Class(result) : result; ++ }; ++ augment(Super, Class, method); ++ augment(Super.prototype, Class.prototype, method); ++ return Class; ++ }; ++ ++ const variables$1 = freeze({ ++ frozen: new WeakMap$3(), ++ hidden: new WeakSet$6(), ++ iframePropertiesToAbort: { ++ read: new Set(), ++ write: new Set() ++ }, ++ abortedIframes: new WeakMap$3() ++ }); ++ ++ const startsCapitalized = new RegExp$1("^[A-Z]"); ++ ++ var env = new Proxy(new Map$5([ ++ ++ ["chrome", ( ++ isExtensionContext$2 && ( ++ (isChrome && chrome) || ++ (isOtherThanChrome && browser) ++ ) ++ ) || void 0], ++ ["isExtensionContext", isExtensionContext$2], ++ ["variables", variables$1], ++ ++ ["console", copyIfExtension(console)], ++ ["document", globalThis.document], ++ ["performance", copyIfExtension(performance)], ++ ["JSON", copyIfExtension(JSON)], ++ ["Map", Map$5], ++ ["Math", copyIfExtension(Math)], ++ ["Number", isExtensionContext$2 ? Number : primitive("Number")], ++ ["RegExp", RegExp$1], ++ ["Set", Set], ++ ["String", isExtensionContext$2 ? String : primitive("String")], ++ ["WeakMap", WeakMap$3], ++ ["WeakSet", WeakSet$6], ++ ++ ["MouseEvent", MouseEvent] ++ ]), { ++ get(map, key) { ++ if (map.has(key)) ++ return map.get(key); ++ ++ let value = globalThis[key]; ++ if (typeof value === "function") ++ value = (startsCapitalized.test(key) ? classes : invokes)[key]; ++ ++ map.set(key, value); ++ return value; ++ }, ++ has(map, key) { ++ return map.has(key); ++ } ++ }); ++ ++ class WeakValue { ++ has() { return false; } ++ set() {} ++ } ++ ++ const helpers = {WeakSet, WeakMap, WeakValue}; ++ const {apply} = Reflect; ++ ++ function transformOnce (callback) { const {WeakSet, WeakMap, WeakValue} = (this || helpers); ++ const ws = new WeakSet; ++ const wm = new WeakMap; ++ const wv = new WeakValue; ++ return function (any) { ++ if (ws.has(any)) ++ return any; ++ ++ if (wm.has(any)) ++ return wm.get(any); ++ ++ if (wv.has(any)) ++ return wv.get(any); ++ ++ const value = apply(callback, this, arguments); ++ ws.add(value); ++ if (value !== any) ++ (typeof any === 'object' && any ? wm : wv).set(any, value); ++ return value; ++ }; ++ } ++ ++ const {Map: Map$4, WeakMap: WeakMap$2, WeakSet: WeakSet$5, setTimeout: setTimeout$2} = env; ++ ++ let cleanup = true; ++ let cleanUpCallback = map => { ++ map.clear(); ++ cleanup = !cleanup; ++ }; ++ ++ var transformer = transformOnce.bind({ ++ WeakMap: WeakMap$2, ++ WeakSet: WeakSet$5, ++ ++ WeakValue: class extends Map$4 { ++ set(key, value) { ++ if (cleanup) { ++ cleanup = !cleanup; ++ setTimeout$2(cleanUpCallback, 0, this); ++ } ++ return super.set(key, value); ++ } ++ } ++ }); ++ ++ const {concat, includes, join, reduce, unshift} = caller([]); ++ ++ const globals = secure(globalThis); ++ ++ const { ++ Map: Map$3, ++ WeakMap: WeakMap$1 ++ } = globals; ++ ++ const map = new Map$3; ++ const descriptors = target => { ++ const chain = []; ++ let current = target; ++ while (current) { ++ if (map.has(current)) ++ unshift(chain, map.get(current)); ++ else { ++ const descriptors = getOwnPropertyDescriptors$1(current); ++ map.set(current, descriptors); ++ unshift(chain, descriptors); ++ } ++ current = getPrototypeOf(current); ++ } ++ unshift(chain, {}); ++ return apply$2(assign$1, null, chain); ++ }; ++ ++ const chain = source => { ++ const target = typeof source === 'function' ? source.prototype : source; ++ const chained = descriptors(target); ++ const handler = { ++ get(target, key) { ++ if (key in chained) { ++ const {value, get} = chained[key]; ++ if (get) ++ return call(get, target); ++ if (typeof value === 'function') ++ return bind(value, target); ++ } ++ return target[key]; ++ }, ++ set(target, key, value) { ++ if (key in chained) { ++ const {set} = chained[key]; ++ if (set) { ++ call(set, target, value); ++ return true; ++ } ++ } ++ target[key] = value; ++ return true; ++ } ++ }; ++ return target => new $$1(target, handler); ++ }; ++ ++ const { ++ isExtensionContext: isExtensionContext$1, ++ Array: Array$2, ++ Number: Number$1, ++ String: String$1, ++ Object: Object$2 ++ } = env; ++ ++ const {isArray} = Array$2; ++ const {getOwnPropertyDescriptor, setPrototypeOf: setPrototypeOf$1} = Object$2; ++ ++ const {toString} = Object$2.prototype; ++ const {slice} = String$1.prototype; ++ const getBrand = value => call(slice, call(toString, value), 8, -1); ++ ++ const {get: nodeType} = getOwnPropertyDescriptor(Node.prototype, "nodeType"); ++ ++ const chained = isExtensionContext$1 ? {} : { ++ Attr: chain(Attr), ++ CanvasRenderingContext2D: chain(CanvasRenderingContext2D), ++ CSSStyleDeclaration: chain(CSSStyleDeclaration), ++ Document: chain(Document), ++ Element: chain(Element), ++ HTMLCanvasElement: chain(HTMLCanvasElement), ++ HTMLElement: chain(HTMLElement), ++ HTMLImageElement: chain(HTMLImageElement), ++ HTMLScriptElement: chain(HTMLScriptElement), ++ MutationRecord: chain(MutationRecord), ++ Node: chain(Node), ++ ShadowRoot: chain(ShadowRoot), ++ ++ get CSS2Properties() { ++ return chained.CSSStyleDeclaration; ++ } ++ }; ++ ++ const upgrade = (value, hint) => { ++ if (hint !== "Element" && hint in chained) ++ return chained[hint](value); ++ ++ if (isArray(value)) ++ return setPrototypeOf$1(value, Array$2.prototype); ++ ++ const brand = getBrand(value); ++ if (brand in chained) ++ return chained[brand](value); ++ ++ if (brand in env) ++ return setPrototypeOf$1(value, env[brand].prototype); ++ ++ if ("nodeType" in value) { ++ switch (call(nodeType, value)) { ++ case 1: ++ if (!(hint in chained)) ++ throw new Error("unknown hint " + hint); ++ return chained[hint](value); ++ case 2: ++ return chained.Attr(value); ++ case 3: ++ return chained.Node(value); ++ case 9: ++ return chained.Document(value); ++ } ++ } ++ ++ throw new Error("unknown brand " + brand); ++ }; ++ ++ var $ = isExtensionContext$1 ? ++ value => (value === window || value === globalThis ? env : value) : ++ transformer((value, hint = "Element") => { ++ if (value === window || value === globalThis) ++ return env; ++ ++ switch (typeof value) { ++ case "object": ++ return value && upgrade(value, hint); ++ ++ case "string": ++ return new String$1(value); ++ ++ case "number": ++ return new Number$1(value); ++ ++ default: ++ throw new Error("unsupported value"); ++ } ++ }); ++ ++ let { ++ document: document$1, ++ getComputedStyle: getComputedStyle$3, ++ isExtensionContext, ++ variables, ++ Array: Array$1, ++ MutationObserver: MutationObserver$7, ++ Object: Object$1, ++ XPathEvaluator, ++ XPathExpression, ++ XPathResult ++ } = $(window); ++ ++ let {querySelectorAll} = document$1; ++ let $$ = querySelectorAll && bind(querySelectorAll, document$1); ++ ++ const {assign, setPrototypeOf} = Object$1; ++ ++ class $XPathExpression extends XPathExpression { ++ evaluate(...args) { ++ return setPrototypeOf( ++ apply$2(super.evaluate, this, args), ++ XPathResult.prototype ++ ); ++ } ++ } ++ ++ class $XPathEvaluator extends XPathEvaluator { ++ createExpression(...args) { ++ return setPrototypeOf( ++ apply$2(super.createExpression, this, args), ++ $XPathExpression.prototype ++ ); ++ } ++ } ++ ++ function hideElement(element) { ++ if (variables.hidden.has(element)) ++ return; ++ ++ notifyElementHidden(element); ++ ++ variables.hidden.add(element); ++ ++ let {style} = $(element); ++ let $style = $(style, "CSSStyleDeclaration"); ++ let properties = $([]); ++ let {debugCSSProperties} = libEnvironment; ++ ++ for (let [key, value] of (debugCSSProperties || [["display", "none"]])) { ++ $style.setProperty(key, value, "important"); ++ properties.push([key, $style.getPropertyValue(key)]); ++ } ++ ++ new MutationObserver$7(() => { ++ for (let [key, value] of properties) { ++ let propertyValue = $style.getPropertyValue(key); ++ let propertyPriority = $style.getPropertyPriority(key); ++ if (propertyValue != value || propertyPriority != "important") ++ $style.setProperty(key, value, "important"); ++ } ++ }).observe(element, {attributes: true, ++ attributeFilter: ["style"]}); ++ } ++ ++ function notifyElementHidden(element) { ++ if (isExtensionContext && typeof checkElement === "function") ++ checkElement(element); ++ } ++ ++ function initQueryAndApply(selector) { ++ let $selector = selector; ++ if ($selector.startsWith("xpath(") && ++ $selector.endsWith(")")) { ++ let xpathQuery = $selector.slice(6, -1); ++ let evaluator = new $XPathEvaluator(); ++ let expression = evaluator.createExpression(xpathQuery, null); ++ ++ let flag = XPathResult.ORDERED_NODE_SNAPSHOT_TYPE; ++ ++ return cb => { ++ if (!cb) ++ return; ++ let result = expression.evaluate(document$1, flag, null); ++ let {snapshotLength} = result; ++ for (let i = 0; i < snapshotLength; i++) ++ cb(result.snapshotItem(i)); ++ }; ++ } ++ return cb => $$(selector).forEach(cb); ++ } ++ ++ function hideIfMatches(match, selector, searchSelector) { ++ if (searchSelector == null) ++ searchSelector = selector; ++ ++ let won; ++ const callback = () => { ++ for (const element of $$(searchSelector)) { ++ const closest = $(element).closest(selector); ++ if (closest && match(element, closest)) { ++ won(); ++ hideElement(closest); ++ } ++ } ++ }; ++ return assign( ++ new MutationObserver$7(callback), ++ { ++ race(win) { ++ won = win; ++ this.observe(document$1, {childList: true, ++ characterData: true, ++ subtree: true}); ++ callback(); ++ } ++ } ++ ); ++ } ++ ++ function isVisible(element, style, closest) { ++ let $style = $(style, "CSSStyleDeclaration"); ++ if ($style.getPropertyValue("display") == "none") ++ return false; ++ ++ let visibility = $style.getPropertyValue("visibility"); ++ if (visibility == "hidden" || visibility == "collapse") ++ return false; ++ ++ if (!closest || element == closest) ++ return true; ++ ++ let parent = $(element).parentElement; ++ if (!parent) ++ return true; ++ ++ return isVisible(parent, getComputedStyle$3(parent), closest); ++ } ++ ++ function getComputedCSSText(element) { ++ let style = getComputedStyle$3(element); ++ let {cssText} = style; ++ ++ if (cssText) ++ return cssText; ++ ++ for (let property of style) ++ cssText += `${property}: ${style[property]}; `; ++ ++ return $(cssText).trim(); ++ } ++ ++ let { ++ parseInt: parseInt$1, ++ setTimeout: setTimeout$1, ++ Error: Error$2, ++ MouseEvent: MouseEvent$1, ++ MutationObserver: MutationObserver$6, ++ WeakSet: WeakSet$4 ++ } = $(window); ++ ++ function simulateEvent(event, selector, delay = "0") { ++ if (!event) ++ throw new Error$2("[simulate-event snippet]: No event type provided."); ++ if (!selector) ++ throw new Error$2("[simulate-event snippet]: No selector provided."); ++ ++ let queryAndApply = initQueryAndApply(selector); ++ let delayInMiliseconds = parseInt$1(delay, 10); ++ let dispatchedNodes = new WeakSet$4(); ++ ++ let observer = new MutationObserver$6(findNodesAndDispatchEvents); ++ observer.observe(document, {childList: true, subtree: true}); ++ findNodesAndDispatchEvents(); ++ ++ function findNodesAndDispatchEvents() { ++ queryAndApply(node => { ++ if (!dispatchedNodes.has(node)) { ++ dispatchedNodes.add(node); ++ setTimeout$1(() => { ++ $(node).dispatchEvent( ++ new MouseEvent$1(event, {bubbles: true, cancelable: true}) ++ ); ++ }, delayInMiliseconds); ++ } ++ }); ++ } ++ } ++ ++ let {Math: Math$2, RegExp} = $(window); ++ ++ function regexEscape(string) { ++ return $(string).replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); ++ } ++ ++ function toRegExp(pattern) { ++ let {length} = pattern; ++ ++ if (length > 1 && pattern[0] === "/") { ++ let isCaseSensitive = pattern[length - 1] === "/"; ++ ++ if (isCaseSensitive || (length > 2 && $(pattern).endsWith("/i"))) { ++ let args = [$(pattern).slice(1, isCaseSensitive ? -1 : -2)]; ++ if (!isCaseSensitive) ++ args.push("i"); ++ ++ return new RegExp(...args); ++ } ++ } ++ ++ return new RegExp(regexEscape(pattern)); ++ } ++ ++ let debugging = false; ++ ++ function debug() { ++ return debugging; ++ } ++ ++ function setDebug() { ++ debugging = true; ++ } ++ ++ const {console: console$1} = $(window); ++ ++ const noop = () => {}; ++ ++ function log(...args) { ++ if (debug()) ++ $(args).unshift("%c DEBUG", "font-weight: bold"); ++ ++ console$1.log(...args); ++ } ++ ++ function getDebugger(name) { ++ return bind(debug() ? log : noop, null, name); ++ } ++ ++ let {Array, Error: Error$1, Map: Map$2, parseInt} = $(window); ++ ++ let stack = null; ++ let won = null; ++ ++ function race(action, winners = "1") { ++ switch (action) { ++ case "start": ++ stack = { ++ winners: parseInt(winners, 10) || 1, ++ participants: new Map$2() ++ }; ++ won = new Array(); ++ break; ++ case "end": ++ case "finish": ++ case "stop": ++ stack = null; ++ for (let win of won) ++ win(); ++ won = null; ++ break; ++ default: ++ throw new Error$1(`Invalid action: ${action}`); ++ } ++ } ++ ++ function raceWinner(name, lose) { ++ ++ if (stack === null) ++ return noop; ++ ++ let current = stack; ++ let {participants} = current; ++ participants.set(win, lose); ++ ++ return win; ++ ++ function win() { ++ ++ if (current.winners < 1) ++ return; ++ ++ let debugLog = getDebugger("race"); ++ debugLog(`${name} won the race`); ++ ++ if (current === stack) { ++ won.push(win); ++ } ++ else { ++ participants.delete(win); ++ if (--current.winners < 1) { ++ for (let looser of participants.values()) ++ looser(); ++ ++ participants.clear(); ++ } ++ } ++ } ++ } ++ ++ function hideIfContains(search, selector = "*", searchSelector = null) { ++ let re = toRegExp(search); ++ ++ const mo = hideIfMatches(element => re.test($(element).textContent), ++ selector, ++ searchSelector); ++ mo.race(raceWinner( ++ "hide-if-contains", ++ () => { ++ mo.disconnect(); ++ } ++ )); ++ } ++ ++ let {MutationObserver: MutationObserver$5} = $(window); ++ ++ function hideIfContainsAndMatchesStyle( ++ search, ++ selector = "*", ++ searchSelector = null, ++ style = null, ++ searchStyle = null ++ ) { ++ if (searchSelector == null) ++ searchSelector = selector; ++ ++ let searchRegExp = toRegExp(search); ++ ++ let styleRegExp = style ? toRegExp(style) : null; ++ let searchStyleRegExp = searchStyle ? toRegExp(searchStyle) : null; ++ ++ let callback = () => { ++ for (let element of $$(searchSelector)) { ++ if (searchRegExp.test($(element).textContent) && ++ (!searchStyleRegExp || ++ searchStyleRegExp.test(getComputedCSSText(element)))) { ++ let closest = $(element).closest(selector); ++ if (closest && (!styleRegExp || ++ styleRegExp.test(getComputedCSSText(closest)))) { ++ win(); ++ hideElement(closest); ++ } ++ } ++ } ++ }; ++ ++ let mo = new MutationObserver$5(callback); ++ let win = raceWinner( ++ "hide-if-contains-and-matches-style", ++ () => mo.disconnect() ++ ); ++ mo.observe(document, {childList: true, characterData: true, subtree: true}); ++ callback(); ++ } ++ ++ let { ++ clearTimeout, ++ fetch, ++ getComputedStyle: getComputedStyle$2, ++ setTimeout, ++ Map: Map$1, ++ MutationObserver: MutationObserver$4, ++ Uint8Array ++ } = $(window); ++ ++ function hideIfContainsImage(search, selector, searchSelector) { ++ if (searchSelector == null) ++ searchSelector = selector; ++ ++ let searchRegExp = toRegExp(search); ++ ++ let callback = () => { ++ for (let element of $$(searchSelector)) { ++ let style = getComputedStyle$2(element); ++ let match = $(style["background-image"]).match(/^url\("(.*)"\)$/); ++ if (match) { ++ fetchContent(match[1]).then(content => { ++ if (searchRegExp.test(uint8ArrayToHex(new Uint8Array(content)))) { ++ let closest = $(element).closest(selector); ++ if (closest) { ++ win(); ++ hideElement(closest); ++ } ++ } ++ }); ++ } ++ } ++ }; ++ ++ let mo = new MutationObserver$4(callback); ++ let win = raceWinner( ++ "hide-if-contains-image", ++ () => mo.disconnect() ++ ); ++ mo.observe(document, {childList: true, subtree: true}); ++ callback(); ++ } ++ ++ let fetchContentMap = new Map$1(); ++ ++ function fetchContent(url, {as = "arrayBuffer", cleanup = 60000} = {}) { ++ ++ let uid = as + ":" + url; ++ let details = fetchContentMap.get(uid) || { ++ remove: () => fetchContentMap.delete(uid), ++ result: null, ++ timer: 0 ++ }; ++ clearTimeout(details.timer); ++ details.timer = setTimeout(details.remove, cleanup); ++ if (!details.result) { ++ details.result = fetch(url).then(res => res[as]()).catch(details.remove); ++ fetchContentMap.set(uid, details); ++ } ++ return details.result; ++ } ++ ++ function toHex(number, length = 2) { ++ let hex = $(number).toString(16); ++ ++ if (hex.length < length) ++ hex = $("0").repeat(length - hex.length) + hex; ++ ++ return hex; ++ } ++ ++ function uint8ArrayToHex(uint8Array) { ++ return uint8Array.reduce((hex, byte) => hex + toHex(byte), ""); ++ } ++ ++ const {parseFloat: parseFloat$1, Math: Math$1, MutationObserver: MutationObserver$3, WeakSet: WeakSet$3} = $(window); ++ const {min} = Math$1; ++ ++ const ld = (a, b) => { ++ const len1 = a.length + 1; ++ const len2 = b.length + 1; ++ const d = [[0]]; ++ let i = 0; ++ let I = 0; ++ ++ while (++i < len2) ++ d[0][i] = i; ++ ++ i = 0; ++ while (++i < len1) { ++ const c = a[I]; ++ let j = 0; ++ let J = 0; ++ d[i] = [i]; ++ while (++j < len2) { ++ d[i][j] = min(d[I][j] + 1, d[i][J] + 1, d[I][J] + (c != b[J])); ++ ++J; ++ } ++ ++I; ++ } ++ return d[len1 - 1][len2 - 1]; ++ }; ++ ++ function hideIfContainsSimilarText( ++ search, selector, ++ searchSelector = null, ++ ignoreChars = 0, ++ maxSearches = 0 ++ ) { ++ const visitedNodes = new WeakSet$3(); ++ const debugLog = getDebugger("hide-if-contains-similar-text"); ++ const $search = $(search); ++ const {length} = $search; ++ const chars = length + parseFloat$1(ignoreChars) || 0; ++ const find = $([...$search]).sort(); ++ const guard = parseFloat$1(maxSearches) || Infinity; ++ ++ if (searchSelector == null) ++ searchSelector = selector; ++ ++ debugLog("Looking for similar text: " + $search); ++ ++ const callback = () => { ++ for (const element of $$(searchSelector)) { ++ if (visitedNodes.has(element)) ++ continue; ++ ++ visitedNodes.add(element); ++ const {innerText} = $(element); ++ const loop = min(guard, innerText.length - chars + 1); ++ for (let i = 0; i < loop; i++) { ++ const str = $(innerText).substr(i, chars); ++ const distance = ld(find, $([...str]).sort()) - ignoreChars; ++ if (distance <= 0) { ++ const closest = $(element).closest(selector); ++ debugLog("Found similar text: " + $search, closest); ++ if (closest) { ++ win(); ++ hideElement(closest); ++ break; ++ } ++ } ++ } ++ } ++ }; ++ ++ let mo = new MutationObserver$3(callback); ++ let win = raceWinner( ++ "hide-if-contains-similar-text", ++ () => mo.disconnect() ++ ); ++ mo.observe(document, {childList: true, characterData: true, subtree: true}); ++ callback(); ++ } ++ ++ let {getComputedStyle: getComputedStyle$1, Map, WeakSet: WeakSet$2, parseFloat} = $(window); ++ ++ const {ELEMENT_NODE: ELEMENT_NODE$1, TEXT_NODE} = Node; ++ ++ function hideIfContainsVisibleText(search, selector, ++ searchSelector = null, ++ ...attributes) { ++ let entries = $([]); ++ const optionalParameters = new Map([ ++ ["-snippet-box-margin", "2"] ++ ]); ++ ++ for (let attr of attributes) { ++ attr = $(attr); ++ let markerIndex = attr.indexOf(":"); ++ if (markerIndex < 0) ++ continue; ++ ++ let key = attr.slice(0, markerIndex).trim().toString(); ++ let value = attr.slice(markerIndex + 1).trim().toString(); ++ ++ if (key && value) { ++ if (optionalParameters.has(key)) ++ optionalParameters.set(key, value); ++ else ++ entries.push([key, value]); ++ } ++ } ++ ++ let defaultEntries = $([ ++ ["opacity", "0"], ++ ["font-size", "0px"], ++ ++ ["color", "rgba(0, 0, 0, 0)"] ++ ]); ++ ++ let attributesMap = new Map(defaultEntries.concat(entries)); ++ ++ function isTextVisible(element, style) { ++ if (!style) ++ style = getComputedStyle$1(element); ++ ++ style = $(style); ++ ++ for (const [key, value] of attributesMap) { ++ let valueAsRegex = toRegExp(value); ++ if (valueAsRegex.test(style.getPropertyValue(key))) ++ return false; ++ } ++ ++ let color = style.getPropertyValue("color"); ++ if (style.getPropertyValue("background-color") == color) ++ return false; ++ ++ return true; ++ } ++ ++ function getPseudoContent(element, pseudo) { ++ let style = getComputedStyle$1(element, pseudo); ++ if (!isVisible(element, style) || !isTextVisible(element, style)) ++ return ""; ++ ++ let {content} = $(style); ++ if (content && content !== "none") { ++ let strings = $([]); ++ ++ content = $(content).trim().replace( ++ /(["'])(?:(?=(\\?))\2.)*?\1/g, ++ value => `\x01${strings.push($(value).slice(1, -1)) - 1}` ++ ); ++ ++ content = content.replace( ++ /\s*attr\(\s*([^\s,)]+)[^)]*?\)\s*/g, ++ (_, name) => $(element).getAttribute(name) || "" ++ ); ++ ++ return content.replace( ++ /\x01(\d+)/g, ++ (_, index) => strings[index]); ++ } ++ return ""; ++ } ++ ++ function isContained(childNode, parentNode, {boxMargin = 2} = {}) { ++ const child = $(childNode).getBoundingClientRect(); ++ const parent = $(parentNode).getBoundingClientRect(); ++ const stretchedParent = { ++ left: parent.left - boxMargin, ++ right: parent.right + boxMargin, ++ top: parent.top - boxMargin, ++ bottom: parent.bottom + boxMargin ++ }; ++ return ( ++ (stretchedParent.left <= child.left && ++ child.left <= stretchedParent.right && ++ stretchedParent.top <= child.top && ++ child.top <= stretchedParent.bottom) && ++ (stretchedParent.top <= child.bottom && ++ child.bottom <= stretchedParent.bottom && ++ stretchedParent.left <= child.right && ++ child.right <= stretchedParent.right) ++ ); ++ } ++ ++ function getVisibleContent(element, ++ closest, ++ style, ++ parentOverflowNode, ++ {boxMargin = 2} = {}) { ++ let checkClosest = !style; ++ if (checkClosest) ++ style = getComputedStyle$1(element); ++ ++ if (!isVisible(element, style, checkClosest && closest)) ++ return ""; ++ ++ if (!parentOverflowNode && ++ ( ++ $(style).getPropertyValue("overflow-x") === "hidden" || ++ $(style).getPropertyValue("overflow-y") === "hidden" ++ ) ++ ) ++ parentOverflowNode = element; ++ ++ let text = getPseudoContent(element, ":before"); ++ for (let node of $(element).childNodes) { ++ switch ($(node).nodeType) { ++ case ELEMENT_NODE$1: ++ text += getVisibleContent(node, ++ element, ++ getComputedStyle$1(node), ++ parentOverflowNode, ++ {boxMargin}); ++ break; ++ case TEXT_NODE: ++ ++ if (parentOverflowNode) { ++ if (isContained(element, parentOverflowNode, {boxMargin}) && ++ isTextVisible(element, style)) ++ text += $(node).nodeValue; ++ } ++ else if (isTextVisible(element, style)) { ++ text += $(node).nodeValue; ++ } ++ break; ++ } ++ } ++ return text + getPseudoContent(element, ":after"); ++ } ++ const boxMarginStr = optionalParameters.get("-snippet-box-margin"); ++ const boxMargin = parseFloat(boxMarginStr) || 0; ++ ++ let re = toRegExp(search); ++ let seen = new WeakSet$2(); ++ ++ const mo = hideIfMatches( ++ (element, closest) => { ++ if (seen.has(element)) ++ return false; ++ ++ seen.add(element); ++ let text = getVisibleContent(element, closest, null, null, {boxMargin}); ++ let result = re.test(text); ++ if (debug() && text.length) ++ log(result, re, text); ++ return result; ++ }, ++ selector, ++ searchSelector ++ ); ++ mo.race(raceWinner( ++ "hide-if-contains-visible-text", ++ () => { ++ mo.disconnect(); ++ } ++ )); ++ } ++ ++ let {MutationObserver: MutationObserver$2} = $(window); ++ ++ function hideIfHasAndMatchesStyle(search, selector = "*", ++ searchSelector = null, style = null, ++ searchStyle = null) { ++ if (searchSelector == null) ++ searchSelector = selector; ++ ++ let styleRegExp = style ? toRegExp(style) : null; ++ let searchStyleRegExp = searchStyle ? toRegExp(searchStyle) : null; ++ ++ let callback = () => { ++ for (let element of $$(searchSelector)) { ++ if ($(element).querySelector(search) && ++ (!searchStyleRegExp || ++ searchStyleRegExp.test(getComputedCSSText(element)))) { ++ let closest = $(element).closest(selector); ++ if (closest && (!styleRegExp || ++ styleRegExp.test(getComputedCSSText(closest)))) { ++ win(); ++ hideElement(closest); ++ } ++ } ++ } ++ }; ++ ++ let mo = new MutationObserver$2(callback); ++ let win = raceWinner( ++ "hide-if-has-and-matches-style", ++ () => mo.disconnect() ++ ); ++ mo.observe(document, {childList: true, subtree: true}); ++ callback(); ++ } ++ ++ let {getComputedStyle, MutationObserver: MutationObserver$1, WeakSet: WeakSet$1} = $(window); ++ ++ function hideIfLabelledBy(search, selector, searchSelector = null) { ++ let sameSelector = searchSelector == null; ++ ++ let searchRegExp = toRegExp(search); ++ ++ let matched = new WeakSet$1(); ++ ++ let callback = () => { ++ for (let node of $$(selector)) { ++ let closest = sameSelector ? ++ node : ++ $(node).closest(searchSelector); ++ if (!closest || !isVisible(node, getComputedStyle(node), closest)) ++ continue; ++ ++ let attr = $(node).getAttribute("aria-labelledby"); ++ let fallback = () => { ++ if (matched.has(closest)) ++ return; ++ ++ if (searchRegExp.test( ++ $(node).getAttribute("aria-label") || "" ++ )) { ++ win(); ++ matched.add(closest); ++ hideElement(closest); ++ } ++ }; ++ ++ if (attr) { ++ for (let label of $(attr).split(/\s+/)) { ++ let target = $(document).getElementById(label); ++ if (target) { ++ if (!matched.has(target) && searchRegExp.test(target.innerText)) { ++ win(); ++ matched.add(target); ++ hideElement(closest); ++ } ++ } ++ else { ++ fallback(); ++ } ++ } ++ } ++ else { ++ fallback(); ++ } ++ } ++ }; ++ ++ let mo = new MutationObserver$1(callback); ++ let win = raceWinner( ++ "hide-if-labelled-by", ++ () => mo.disconnect() ++ ); ++ mo.observe(document, {characterData: true, childList: true, subtree: true}); ++ callback(); ++ } ++ ++ $(window); ++ ++ const noopProfile = { ++ mark() {}, ++ end() {}, ++ toString() { ++ return "{mark(){},end(){}}"; ++ } ++ }; ++ ++ function profile(id, rate = 10) { ++ return noopProfile; ++ } ++ ++ let {MutationObserver} = $(window); ++ ++ const {ELEMENT_NODE} = Node; ++ ++ function hideIfMatchesXPath(query) { ++ let {mark, end} = profile(); ++ ++ let queryAndApply = initQueryAndApply(`xpath(${query})`); ++ ++ let callback = () => { ++ mark(); ++ ++ queryAndApply(node => { ++ win(); ++ if ($(node).nodeType === ELEMENT_NODE) ++ hideElement(node); ++ else ++ $(node).textContent = ""; ++ }); ++ ++ end(); ++ }; ++ ++ let mo = new MutationObserver(callback); ++ let win = raceWinner( ++ "hide-if-matches-xpath", ++ () => mo.disconnect() ++ ); ++ mo.observe(document, {characterData: true, childList: true, subtree: true}); ++ callback(); ++ } ++ ++ const snippets = { ++ log, ++ race, ++ "debug": setDebug, ++ "hide-if-matches-xpath": hideIfMatchesXPath, ++ "hide-if-contains": hideIfContains, ++ "hide-if-contains-similar-text": hideIfContainsSimilarText, ++ "hide-if-contains-visible-text": hideIfContainsVisibleText, ++ "hide-if-contains-and-matches-style": hideIfContainsAndMatchesStyle, ++ "hide-if-has-and-matches-style": hideIfHasAndMatchesStyle, ++ "hide-if-labelled-by": hideIfLabelledBy, ++ "hide-if-contains-image": hideIfContainsImage, ++ "simulate-event-poc": simulateEvent ++ }; ++ let context; ++ for (const [name, ...args] of filters) { ++ if (snippets.hasOwnProperty(name)) { ++ try { context = snippets[name].apply(context, args); } ++ catch (error) { console.error(error); } ++ } ++ } ++ context = void 0; ++})(e, ...t); ++ ++const callback = (environment, ...filters) => { ++ /*! ++ * This file is part of eyeo's Anti-Circumvention Snippets module (@eyeo/snippets), ++ * Copyright (C) 2006-present eyeo GmbH ++ * ++ * @eyeo/snippets 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/snippets 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/snippets. If not, see . ++ */ ++ const $$1 = Proxy; ++ ++ const {apply: a, bind: b, call: c} = Function; ++ const apply$2 = c.bind(a); ++ const bind = c.bind(b); ++ const call = c.bind(c); ++ ++ const callerHandler = { ++ get(target, name) { ++ return bind(c, target[name]); ++ } ++ }; ++ ++ const caller = target => new $$1(target, callerHandler); ++ ++ const proxy = (source, target) => new $$1(source, { ++ apply: (_, self, args) => apply$2(target, self, args) ++ }); ++ ++ const handler$2 = { ++ get(target, name) { ++ return bind(target[name], target); ++ } ++ }; ++ ++ const bound = target => new $$1(target, handler$2); ++ ++ const { ++ assign: assign$1, ++ defineProperties: defineProperties$1, ++ freeze: freeze$1, ++ getOwnPropertyDescriptor: getOwnPropertyDescriptor$3, ++ getOwnPropertyDescriptors: getOwnPropertyDescriptors$1, ++ getPrototypeOf ++ } = bound(Object); ++ ++ const {hasOwnProperty} = caller({}); ++ ++ const {species} = Symbol; ++ ++ const handler$1 = { ++ get(target, name) { ++ const Native = target[name]; ++ class Secure extends Native {} ++ ++ const proto = getOwnPropertyDescriptors$1(Native.prototype); ++ delete proto.constructor; ++ freeze$1(defineProperties$1(Secure.prototype, proto)); ++ ++ const statics = getOwnPropertyDescriptors$1(Native); ++ delete statics.length; ++ delete statics.prototype; ++ statics[species] = {value: Secure}; ++ return freeze$1(defineProperties$1(Secure, statics)); ++ } ++ }; ++ ++ const secure = target => new $$1(target, handler$1); ++ ++ const libEnvironment = typeof environment !== "undefined" ? environment : ++ {}; ++ ++ if (typeof globalThis === "undefined") ++ window.globalThis = window; ++ ++ const {apply: apply$1, ownKeys} = bound(Reflect); ++ ++ const worldEnvDefined = "world" in libEnvironment; ++ const isIsolatedWorld = worldEnvDefined && libEnvironment.world === "ISOLATED"; ++ const isMainWorld = worldEnvDefined && libEnvironment.world === "MAIN"; ++ const isChrome = typeof chrome === "object" && !!chrome.runtime; ++ const isOtherThanChrome = typeof browser === "object" && !!browser.runtime; ++ const isExtensionContext$2 = !isMainWorld && ++ (isIsolatedWorld || isChrome || isOtherThanChrome); ++ const copyIfExtension = value => isExtensionContext$2 ? ++ value : ++ create(value, getOwnPropertyDescriptors(value)); ++ ++ const { ++ create, ++ defineProperties, ++ defineProperty, ++ freeze, ++ getOwnPropertyDescriptor: getOwnPropertyDescriptor$2, ++ getOwnPropertyDescriptors ++ } = bound(Object); ++ ++ const invokes = bound(globalThis); ++ const classes = isExtensionContext$2 ? globalThis : secure(globalThis); ++ const {Map: Map$8, RegExp: RegExp$1, Set: Set$2, WeakMap: WeakMap$4, WeakSet: WeakSet$3} = classes; ++ ++ const augment = (source, target, method = null) => { ++ const known = ownKeys(target); ++ for (const key of ownKeys(source)) { ++ if (known.includes(key)) ++ continue; ++ ++ const descriptor = getOwnPropertyDescriptor$2(source, key); ++ if (method && "value" in descriptor) { ++ const {value} = descriptor; ++ if (typeof value === "function") ++ descriptor.value = method(value); ++ } ++ defineProperty(target, key, descriptor); ++ } ++ }; ++ ++ const primitive = name => { ++ const Super = classes[name]; ++ class Class extends Super {} ++ const {toString, valueOf} = Super.prototype; ++ defineProperties(Class.prototype, { ++ toString: {value: toString}, ++ valueOf: {value: valueOf} ++ }); ++ const type = name.toLowerCase(); ++ const method = callback => function() { ++ const result = apply$1(callback, this, arguments); ++ return typeof result === type ? new Class(result) : result; ++ }; ++ augment(Super, Class, method); ++ augment(Super.prototype, Class.prototype, method); ++ return Class; ++ }; ++ ++ const variables$3 = freeze({ ++ frozen: new WeakMap$4(), ++ hidden: new WeakSet$3(), ++ iframePropertiesToAbort: { ++ read: new Set$2(), ++ write: new Set$2() ++ }, ++ abortedIframes: new WeakMap$4() ++ }); ++ ++ const startsCapitalized = new RegExp$1("^[A-Z]"); ++ ++ var env = new Proxy(new Map$8([ ++ ++ ["chrome", ( ++ isExtensionContext$2 && ( ++ (isChrome && chrome) || ++ (isOtherThanChrome && browser) ++ ) ++ ) || void 0], ++ ["isExtensionContext", isExtensionContext$2], ++ ["variables", variables$3], ++ ++ ["console", copyIfExtension(console)], ++ ["document", globalThis.document], ++ ["performance", copyIfExtension(performance)], ++ ["JSON", copyIfExtension(JSON)], ++ ["Map", Map$8], ++ ["Math", copyIfExtension(Math)], ++ ["Number", isExtensionContext$2 ? Number : primitive("Number")], ++ ["RegExp", RegExp$1], ++ ["Set", Set$2], ++ ["String", isExtensionContext$2 ? String : primitive("String")], ++ ["WeakMap", WeakMap$4], ++ ["WeakSet", WeakSet$3], ++ ++ ["MouseEvent", MouseEvent] ++ ]), { ++ get(map, key) { ++ if (map.has(key)) ++ return map.get(key); ++ ++ let value = globalThis[key]; ++ if (typeof value === "function") ++ value = (startsCapitalized.test(key) ? classes : invokes)[key]; ++ ++ map.set(key, value); ++ return value; ++ }, ++ has(map, key) { ++ return map.has(key); ++ } ++ }); ++ ++ class WeakValue { ++ has() { return false; } ++ set() {} ++ } ++ ++ const helpers = {WeakSet, WeakMap, WeakValue}; ++ const {apply} = Reflect; ++ ++ function transformOnce (callback) { const {WeakSet, WeakMap, WeakValue} = (this || helpers); ++ const ws = new WeakSet; ++ const wm = new WeakMap; ++ const wv = new WeakValue; ++ return function (any) { ++ if (ws.has(any)) ++ return any; ++ ++ if (wm.has(any)) ++ return wm.get(any); ++ ++ if (wv.has(any)) ++ return wv.get(any); ++ ++ const value = apply(callback, this, arguments); ++ ws.add(value); ++ if (value !== any) ++ (typeof any === 'object' && any ? wm : wv).set(any, value); ++ return value; ++ }; ++ } ++ ++ const {Map: Map$7, WeakMap: WeakMap$3, WeakSet: WeakSet$2, setTimeout} = env; ++ ++ let cleanup = true; ++ let cleanUpCallback = map => { ++ map.clear(); ++ cleanup = !cleanup; ++ }; ++ ++ var transformer = transformOnce.bind({ ++ WeakMap: WeakMap$3, ++ WeakSet: WeakSet$2, ++ ++ WeakValue: class extends Map$7 { ++ set(key, value) { ++ if (cleanup) { ++ cleanup = !cleanup; ++ setTimeout(cleanUpCallback, 0, this); ++ } ++ return super.set(key, value); ++ } ++ } ++ }); ++ ++ const {concat, includes, join, reduce, unshift} = caller([]); ++ ++ const globals = secure(globalThis); ++ ++ const { ++ Map: Map$6, ++ WeakMap: WeakMap$2 ++ } = globals; ++ ++ const map = new Map$6; ++ const descriptors = target => { ++ const chain = []; ++ let current = target; ++ while (current) { ++ if (map.has(current)) ++ unshift(chain, map.get(current)); ++ else { ++ const descriptors = getOwnPropertyDescriptors$1(current); ++ map.set(current, descriptors); ++ unshift(chain, descriptors); ++ } ++ current = getPrototypeOf(current); ++ } ++ unshift(chain, {}); ++ return apply$2(assign$1, null, chain); ++ }; ++ ++ const chain = source => { ++ const target = typeof source === 'function' ? source.prototype : source; ++ const chained = descriptors(target); ++ const handler = { ++ get(target, key) { ++ if (key in chained) { ++ const {value, get} = chained[key]; ++ if (get) ++ return call(get, target); ++ if (typeof value === 'function') ++ return bind(value, target); ++ } ++ return target[key]; ++ }, ++ set(target, key, value) { ++ if (key in chained) { ++ const {set} = chained[key]; ++ if (set) { ++ call(set, target, value); ++ return true; ++ } ++ } ++ target[key] = value; ++ return true; ++ } ++ }; ++ return target => new $$1(target, handler); ++ }; ++ ++ const { ++ isExtensionContext: isExtensionContext$1, ++ Array: Array$2, ++ Number: Number$1, ++ String: String$1, ++ Object: Object$9 ++ } = env; ++ ++ const {isArray} = Array$2; ++ const {getOwnPropertyDescriptor: getOwnPropertyDescriptor$1, setPrototypeOf: setPrototypeOf$1} = Object$9; ++ ++ const {toString: toString$1} = Object$9.prototype; ++ const {slice} = String$1.prototype; ++ const getBrand = value => call(slice, call(toString$1, value), 8, -1); ++ ++ const {get: nodeType} = getOwnPropertyDescriptor$1(Node.prototype, "nodeType"); ++ ++ const chained = isExtensionContext$1 ? {} : { ++ Attr: chain(Attr), ++ CanvasRenderingContext2D: chain(CanvasRenderingContext2D), ++ CSSStyleDeclaration: chain(CSSStyleDeclaration), ++ Document: chain(Document), ++ Element: chain(Element), ++ HTMLCanvasElement: chain(HTMLCanvasElement), ++ HTMLElement: chain(HTMLElement), ++ HTMLImageElement: chain(HTMLImageElement), ++ HTMLScriptElement: chain(HTMLScriptElement), ++ MutationRecord: chain(MutationRecord), ++ Node: chain(Node), ++ ShadowRoot: chain(ShadowRoot), ++ ++ get CSS2Properties() { ++ return chained.CSSStyleDeclaration; ++ } ++ }; ++ ++ const upgrade = (value, hint) => { ++ if (hint !== "Element" && hint in chained) ++ return chained[hint](value); ++ ++ if (isArray(value)) ++ return setPrototypeOf$1(value, Array$2.prototype); ++ ++ const brand = getBrand(value); ++ if (brand in chained) ++ return chained[brand](value); ++ ++ if (brand in env) ++ return setPrototypeOf$1(value, env[brand].prototype); ++ ++ if ("nodeType" in value) { ++ switch (call(nodeType, value)) { ++ case 1: ++ if (!(hint in chained)) ++ throw new Error("unknown hint " + hint); ++ return chained[hint](value); ++ case 2: ++ return chained.Attr(value); ++ case 3: ++ return chained.Node(value); ++ case 9: ++ return chained.Document(value); ++ } ++ } ++ ++ throw new Error("unknown brand " + brand); ++ }; ++ ++ var $ = isExtensionContext$1 ? ++ value => (value === window || value === globalThis ? env : value) : ++ transformer((value, hint = "Element") => { ++ if (value === window || value === globalThis) ++ return env; ++ ++ switch (typeof value) { ++ case "object": ++ return value && upgrade(value, hint); ++ ++ case "string": ++ return new String$1(value); ++ ++ case "number": ++ return new Number$1(value); ++ ++ default: ++ throw new Error("unsupported value"); ++ } ++ }); ++ ++ const handler = { ++ get(target, name) { ++ const context = target; ++ while (!hasOwnProperty(target, name)) ++ target = getPrototypeOf(target); ++ const {get, set} = getOwnPropertyDescriptor$3(target, name); ++ return function () { ++ return arguments.length ? ++ apply$2(set, context, arguments) : ++ call(get, context); ++ }; ++ } ++ }; ++ ++ const accessor = target => new $$1(target, handler); ++ ++ let debugging = false; ++ ++ function debug() { ++ return debugging; ++ } ++ ++ function setDebug() { ++ debugging = true; ++ } ++ ++ const {console: console$3} = $(window); ++ ++ const noop = () => {}; ++ ++ function log(...args) { ++ if (debug()) ++ $(args).unshift("%c DEBUG", "font-weight: bold"); ++ ++ console$3.log(...args); ++ } ++ ++ function getDebugger(name) { ++ return bind(debug() ? log : noop, null, name); ++ } ++ ++ let {Math: Math$1, RegExp} = $(window); ++ ++ function regexEscape(string) { ++ return $(string).replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&"); ++ } ++ ++ function toRegExp(pattern) { ++ let {length} = pattern; ++ ++ if (length > 1 && pattern[0] === "/") { ++ let isCaseSensitive = pattern[length - 1] === "/"; ++ ++ if (isCaseSensitive || (length > 2 && $(pattern).endsWith("/i"))) { ++ let args = [$(pattern).slice(1, isCaseSensitive ? -1 : -2)]; ++ if (!isCaseSensitive) ++ args.push("i"); ++ ++ return new RegExp(...args); ++ } ++ } ++ ++ return new RegExp(regexEscape(pattern)); ++ } ++ ++ function randomId() { ++ ++ return $(Math$1.floor(Math$1.random() * 2116316160 + 60466176)).toString(36); ++ } ++ ++ let { ++ parseFloat, ++ variables: variables$2, ++ Array: Array$1, ++ Error: Error$7, ++ Map: Map$5, ++ Object: Object$8, ++ ReferenceError: ReferenceError$2, ++ Set: Set$1, ++ WeakMap: WeakMap$1 ++ } = $(window); ++ ++ let {onerror} = accessor(window); ++ ++ let NodeProto$1 = Node.prototype; ++ let ElementProto$2 = Element.prototype; ++ ++ let propertyAccessors = null; ++ ++ function wrapPropertyAccess(object, property, descriptor) { ++ let $property = $(property); ++ let dotIndex = $property.indexOf("."); ++ if (dotIndex == -1) { ++ ++ let currentDescriptor = Object$8.getOwnPropertyDescriptor(object, property); ++ if (currentDescriptor && !currentDescriptor.configurable) ++ return; ++ ++ let newDescriptor = Object$8.assign({}, descriptor, { ++ configurable: true ++ }); ++ ++ if (!currentDescriptor && !newDescriptor.get && newDescriptor.set) { ++ let propertyValue = object[property]; ++ newDescriptor.get = () => propertyValue; ++ } ++ ++ Object$8.defineProperty(object, property, newDescriptor); ++ return; ++ } ++ ++ let name = $property.slice(0, dotIndex).toString(); ++ property = $property.slice(dotIndex + 1).toString(); ++ let value = object[name]; ++ if (value && (typeof value == "object" || typeof value == "function")) ++ wrapPropertyAccess(value, property, descriptor); ++ ++ let currentDescriptor = Object$8.getOwnPropertyDescriptor(object, name); ++ if (currentDescriptor && !currentDescriptor.configurable) ++ return; ++ ++ if (!propertyAccessors) ++ propertyAccessors = new WeakMap$1(); ++ ++ if (!propertyAccessors.has(object)) ++ propertyAccessors.set(object, new Map$5()); ++ ++ let properties = propertyAccessors.get(object); ++ if (properties.has(name)) { ++ properties.get(name).set(property, descriptor); ++ return; ++ } ++ ++ let toBeWrapped = new Map$5([[property, descriptor]]); ++ properties.set(name, toBeWrapped); ++ Object$8.defineProperty(object, name, { ++ get: () => value, ++ set(newValue) { ++ value = newValue; ++ if (value && (typeof value == "object" || typeof value == "function")) { ++ ++ for (let [prop, desc] of toBeWrapped) ++ wrapPropertyAccess(value, prop, desc); ++ } ++ }, ++ configurable: true ++ }); ++ } ++ ++ function overrideOnError(magic) { ++ let prev = onerror(); ++ onerror((...args) => { ++ let message = args.length && args[0]; ++ if (typeof message == "string" && $(message).includes(magic)) ++ return true; ++ if (typeof prev == "function") ++ return apply$2(prev, this, args); ++ }); ++ } ++ ++ function abortOnRead(loggingPrefix, context, property) { ++ let debugLog = getDebugger(loggingPrefix); ++ ++ if (!property) { ++ debugLog("no property to abort on read"); ++ return; ++ } ++ ++ let rid = randomId(); ++ ++ function abort() { ++ debugLog(`${property} access aborted`); ++ throw new ReferenceError$2(rid); ++ } ++ ++ debugLog(`aborting on ${property} access`); ++ ++ wrapPropertyAccess(context, property, {get: abort, set() {}}); ++ overrideOnError(rid); ++ } ++ ++ function abortOnWrite(loggingPrefix, context, property) { ++ let debugLog = getDebugger(loggingPrefix); ++ ++ if (!property) { ++ debugLog("no property to abort on write"); ++ return; ++ } ++ ++ let rid = randomId(); ++ ++ function abort() { ++ debugLog(`setting ${property} aborted`); ++ throw new ReferenceError$2(rid); ++ } ++ ++ debugLog(`aborting when setting ${property}`); ++ ++ wrapPropertyAccess(context, property, {set: abort}); ++ overrideOnError(rid); ++ } ++ ++ function abortOnIframe( ++ properties, ++ abortRead = false, ++ abortWrite = false ++ ) { ++ let abortedIframes = variables$2.abortedIframes; ++ let iframePropertiesToAbort = variables$2.iframePropertiesToAbort; ++ ++ for (let frame of Array$1.from(window.frames)) { ++ if (abortedIframes.has(frame)) { ++ for (let property of properties) { ++ if (abortRead) ++ abortedIframes.get(frame).read.add(property); ++ if (abortWrite) ++ abortedIframes.get(frame).write.add(property); ++ } ++ } ++ } ++ ++ for (let property of properties) { ++ if (abortRead) ++ iframePropertiesToAbort.read.add(property); ++ if (abortWrite) ++ iframePropertiesToAbort.write.add(property); ++ } ++ ++ queryAndProxyIframe(); ++ if (!abortedIframes.has(document)) { ++ abortedIframes.set(document, true); ++ addHooksOnDomAdditions(queryAndProxyIframe); ++ } ++ ++ function queryAndProxyIframe() { ++ for (let frame of Array$1.from(window.frames)) { ++ ++ if (!abortedIframes.has(frame)) { ++ abortedIframes.set(frame, { ++ read: new Set$1(iframePropertiesToAbort.read), ++ write: new Set$1(iframePropertiesToAbort.write) ++ }); ++ } ++ ++ let readProps = abortedIframes.get(frame).read; ++ if (readProps.size > 0) { ++ let props = Array$1.from(readProps); ++ readProps.clear(); ++ for (let property of props) ++ abortOnRead("abort-on-iframe-property-read", frame, property); ++ } ++ ++ let writeProps = abortedIframes.get(frame).write; ++ if (writeProps.size > 0) { ++ let props = Array$1.from(writeProps); ++ writeProps.clear(); ++ for (let property of props) ++ abortOnWrite("abort-on-iframe-property-write", frame, property); ++ } ++ } ++ } ++ } ++ ++ function addHooksOnDomAdditions(endCallback) { ++ let descriptor; ++ ++ wrapAccess(NodeProto$1, ["appendChild", "insertBefore", "replaceChild"]); ++ wrapAccess(ElementProto$2, ["append", "prepend", "replaceWith", "after", ++ "before", "insertAdjacentElement", ++ "insertAdjacentHTML"]); ++ ++ descriptor = getInnerHTMLDescriptor(ElementProto$2, "innerHTML"); ++ wrapPropertyAccess(ElementProto$2, "innerHTML", descriptor); ++ ++ descriptor = getInnerHTMLDescriptor(ElementProto$2, "outerHTML"); ++ wrapPropertyAccess(ElementProto$2, "outerHTML", descriptor); ++ ++ function wrapAccess(prototype, names) { ++ for (let name of names) { ++ let desc = getAppendChildDescriptor(prototype, name); ++ wrapPropertyAccess(prototype, name, desc); ++ } ++ } ++ ++ function getAppendChildDescriptor(target, property) { ++ let currentValue = target[property]; ++ return { ++ get() { ++ return function(...args) { ++ let result; ++ result = apply$2(currentValue, this, args); ++ endCallback && endCallback(); ++ return result; ++ }; ++ } ++ }; ++ } ++ ++ function getInnerHTMLDescriptor(target, property) { ++ let desc = Object$8.getOwnPropertyDescriptor(target, property); ++ let {set: prevSetter} = desc || {}; ++ return { ++ set(val) { ++ let result; ++ result = call(prevSetter, this, val); ++ endCallback && endCallback(); ++ return result; ++ } ++ }; ++ } ++ } ++ ++ let {Object: NativeObject} = window; ++ function findOwner(root, path) { ++ if (!(root instanceof NativeObject)) ++ return; ++ ++ let object = root; ++ let chain = $(path).split("."); ++ ++ if (chain.length === 0) ++ return; ++ ++ for (let i = 0; i < chain.length - 1; i++) { ++ let prop = chain[i]; ++ ++ if (!hasOwnProperty(object, prop)) ++ return; ++ ++ object = object[prop]; ++ ++ if (!(object instanceof NativeObject)) ++ return; ++ } ++ ++ let prop = chain[chain.length - 1]; ++ ++ if (hasOwnProperty(object, prop)) ++ return [object, prop]; ++ } ++ ++ const decimals = $(/^\d+$/); ++ ++ function overrideValue(value) { ++ switch (value) { ++ case "false": ++ return false; ++ case "true": ++ return true; ++ case "null": ++ return null; ++ case "noopFunc": ++ return () => {}; ++ case "trueFunc": ++ return () => true; ++ case "falseFunc": ++ return () => false; ++ case "emptyArray": ++ return []; ++ case "emptyObj": ++ return {}; ++ case "undefined": ++ return void 0; ++ case "": ++ return value; ++ default: ++ if (decimals.test(value)) ++ return parseFloat(value); ++ ++ throw new Error$7("[override-property-read snippet]: " + ++ `Value "${value}" is not valid.`); ++ } ++ } ++ ++ let {HTMLScriptElement: HTMLScriptElement$1, Object: Object$7, ReferenceError: ReferenceError$1} = $(window); ++ let Script = Object$7.getPrototypeOf(HTMLScriptElement$1); ++ ++ function abortCurrentInlineScript(api, search = null) { ++ let re = search ? toRegExp(search) : null; ++ ++ let rid = randomId(); ++ let us = $(document).currentScript; ++ ++ let object = window; ++ let path = $(api).split("."); ++ let name = $(path).pop(); ++ ++ for (let node of $(path)) { ++ object = object[node]; ++ ++ if (!object || !(typeof object == "object" || typeof object == "function")) ++ return; ++ } ++ ++ let {get: prevGetter, set: prevSetter} = ++ Object$7.getOwnPropertyDescriptor(object, name) || {}; ++ ++ let currentValue = object[name]; ++ ++ let abort = () => { ++ let element = $(document).currentScript; ++ if (element instanceof Script && ++ $(element, "HTMLScriptElement").src == "" && ++ element != us && ++ (!re || re.test($(element).textContent))) ++ throw new ReferenceError$1(rid); ++ }; ++ ++ let descriptor = { ++ get() { ++ abort(); ++ ++ if (prevGetter) ++ return call(prevGetter, this); ++ ++ return currentValue; ++ }, ++ set(value) { ++ abort(); ++ ++ if (prevSetter) ++ call(prevSetter, this, value); ++ else ++ currentValue = value; ++ } ++ }; ++ ++ wrapPropertyAccess(object, name, descriptor); ++ ++ overrideOnError(rid); ++ } ++ ++ function abortOnIframePropertyRead(...properties) { ++ abortOnIframe(properties, true, false); ++ } ++ ++ function abortOnIframePropertyWrite(...properties) { ++ abortOnIframe(properties, false, true); ++ } ++ ++ function abortOnPropertyRead(property) { ++ abortOnRead("abort-on-property-read", window, property); ++ } ++ ++ function abortOnPropertyWrite(property) { ++ abortOnWrite("abort-on-property-write", window, property); ++ } ++ ++ let {Error: Error$6} = $(window); ++ let {cookie: documentCookies} = accessor(document); ++ ++ function cookieRemover(cookie) { ++ if (!cookie) ++ throw new Error$6("[cookie-remover snippet]: No cookie to remove."); ++ ++ let debugLog = getDebugger("cookie-remover"); ++ let re = toRegExp(cookie); ++ ++ if (!$(/^http|^about/).test(location.protocol)) { ++ debugLog("Snippet only works for http or https and about."); ++ return; ++ } ++ ++ debugLog("Parsing cookies for matches"); ++ ++ for (const pair of $(getCookieMatches())) { ++ let $hostname = $(location.hostname); ++ let name = $(pair).split("=")[0]; ++ let expires = "expires=Thu, 01 Jan 1970 00:00:00 GMT"; ++ let path = "path=/"; ++ let domain = "domain=" + $hostname.slice($hostname.indexOf(".") + 1); ++ ++ documentCookies(`${$(name).trim()}=;${expires};${path};${domain}`); ++ ++ debugLog(`Set expiration date on ${name}`); ++ } ++ ++ function getCookieMatches() { ++ const arr = $(documentCookies()).split(";"); ++ return arr.filter(str => re.test($(str).split("=")[0])); ++ } ++ } ++ ++ let { ++ document: document$1, ++ getComputedStyle, ++ isExtensionContext, ++ variables: variables$1, ++ Array, ++ MutationObserver: MutationObserver$2, ++ Object: Object$6, ++ XPathEvaluator, ++ XPathExpression, ++ XPathResult ++ } = $(window); ++ ++ let {querySelectorAll} = document$1; ++ let $$ = querySelectorAll && bind(querySelectorAll, document$1); ++ ++ const {assign, setPrototypeOf} = Object$6; ++ ++ class $XPathExpression extends XPathExpression { ++ evaluate(...args) { ++ return setPrototypeOf( ++ apply$2(super.evaluate, this, args), ++ XPathResult.prototype ++ ); ++ } ++ } ++ ++ class $XPathEvaluator extends XPathEvaluator { ++ createExpression(...args) { ++ return setPrototypeOf( ++ apply$2(super.createExpression, this, args), ++ $XPathExpression.prototype ++ ); ++ } ++ } ++ ++ function hideElement(element) { ++ if (variables$1.hidden.has(element)) ++ return; ++ ++ notifyElementHidden(element); ++ ++ variables$1.hidden.add(element); ++ ++ let {style} = $(element); ++ let $style = $(style, "CSSStyleDeclaration"); ++ let properties = $([]); ++ let {debugCSSProperties} = libEnvironment; ++ ++ for (let [key, value] of (debugCSSProperties || [["display", "none"]])) { ++ $style.setProperty(key, value, "important"); ++ properties.push([key, $style.getPropertyValue(key)]); ++ } ++ ++ new MutationObserver$2(() => { ++ for (let [key, value] of properties) { ++ let propertyValue = $style.getPropertyValue(key); ++ let propertyPriority = $style.getPropertyPriority(key); ++ if (propertyValue != value || propertyPriority != "important") ++ $style.setProperty(key, value, "important"); ++ } ++ }).observe(element, {attributes: true, ++ attributeFilter: ["style"]}); ++ } ++ ++ function notifyElementHidden(element) { ++ if (isExtensionContext && typeof checkElement === "function") ++ checkElement(element); ++ } ++ ++ function initQueryAndApply(selector) { ++ let $selector = selector; ++ if ($selector.startsWith("xpath(") && ++ $selector.endsWith(")")) { ++ let xpathQuery = $selector.slice(6, -1); ++ let evaluator = new $XPathEvaluator(); ++ let expression = evaluator.createExpression(xpathQuery, null); ++ ++ let flag = XPathResult.ORDERED_NODE_SNAPSHOT_TYPE; ++ ++ return cb => { ++ if (!cb) ++ return; ++ let result = expression.evaluate(document$1, flag, null); ++ let {snapshotLength} = result; ++ for (let i = 0; i < snapshotLength; i++) ++ cb(result.snapshotItem(i)); ++ }; ++ } ++ return cb => $$(selector).forEach(cb); ++ } ++ ++ function initQueryAll(selector) { ++ let $selector = selector; ++ if ($selector.startsWith("xpath(") && ++ $selector.endsWith(")")) { ++ let queryAndApply = initQueryAndApply(selector); ++ return () => { ++ let elements = $([]); ++ queryAndApply(e => elements.push(e)); ++ return elements; ++ }; ++ } ++ return () => Array.from($$(selector)); ++ } ++ ++ let {ELEMENT_NODE, TEXT_NODE, prototype: NodeProto} = Node; ++ let {prototype: ElementProto$1} = Element; ++ let {prototype: HTMLElementProto} = HTMLElement; ++ ++ let { ++ console: console$2, ++ variables, ++ DOMParser, ++ Error: Error$5, ++ MutationObserver: MutationObserver$1, ++ Object: Object$5, ++ ReferenceError ++ } = $(window); ++ ++ let {getOwnPropertyDescriptor} = Object$5; ++ ++ function freezeElement(selector, options = "", ...exceptions) { ++ let observer; ++ let subtree = false; ++ let shouldAbort = false; ++ let exceptionSelectors = $(exceptions).filter(e => !isRegex(e)); ++ let regexExceptions = $(exceptions).filter(e => isRegex(e)).map(toRegExp); ++ let rid = randomId(); ++ let targetNodes; ++ let queryAll = initQueryAll(selector); ++ ++ checkOptions(); ++ let data = { ++ selector, ++ shouldAbort, ++ rid, ++ exceptionSelectors, ++ regexExceptions, ++ changeId: 0 ++ }; ++ if (!variables.frozen.has(document)) { ++ variables.frozen.set(document, true); ++ proxyNativeProperties(); ++ } ++ observer = new MutationObserver$1(searchAndAttach); ++ observer.observe(document, {childList: true, subtree: true}); ++ searchAndAttach(); ++ ++ function isRegex(s) { ++ return s.length >= 2 && s[0] == "/" && s[s.length - 1] == "/"; ++ } ++ ++ function checkOptions() { ++ let optionsChunks = $(options).split("+"); ++ if (optionsChunks.length === 1 && optionsChunks[0] === "") ++ optionsChunks = []; ++ for (let chunk of optionsChunks) { ++ switch (chunk) { ++ case "subtree": ++ subtree = true; ++ break; ++ case "abort": ++ shouldAbort = true; ++ break; ++ default: ++ throw new Error$5("[freeze] Unknown option passed to the snippet." + ++ " [selector]: " + selector + ++ " [option]: " + chunk); ++ } ++ } ++ } ++ ++ function proxyNativeProperties() { ++ let descriptor; ++ ++ descriptor = getAppendChildDescriptor( ++ NodeProto, "appendChild", isFrozen, getSnippetData ++ ); ++ wrapPropertyAccess(NodeProto, "appendChild", descriptor); ++ ++ descriptor = getAppendChildDescriptor( ++ NodeProto, "insertBefore", isFrozen, getSnippetData ++ ); ++ wrapPropertyAccess(NodeProto, "insertBefore", descriptor); ++ ++ descriptor = getAppendChildDescriptor( ++ NodeProto, "replaceChild", isFrozen, getSnippetData ++ ); ++ wrapPropertyAccess(NodeProto, "replaceChild", descriptor); ++ ++ descriptor = getAppendDescriptor( ++ ElementProto$1, "append", isFrozen, getSnippetData ++ ); ++ wrapPropertyAccess(ElementProto$1, "append", descriptor); ++ ++ descriptor = getAppendDescriptor( ++ ElementProto$1, "prepend", isFrozen, getSnippetData ++ ); ++ wrapPropertyAccess(ElementProto$1, "prepend", descriptor); ++ ++ descriptor = getAppendDescriptor( ++ ElementProto$1, ++ "replaceWith", ++ isFrozenOrHasFrozenParent, ++ getSnippetDataFromNodeOrParent ++ ); ++ wrapPropertyAccess(ElementProto$1, "replaceWith", descriptor); ++ ++ descriptor = getAppendDescriptor( ++ ElementProto$1, ++ "after", ++ isFrozenOrHasFrozenParent, ++ getSnippetDataFromNodeOrParent ++ ); ++ wrapPropertyAccess(ElementProto$1, "after", descriptor); ++ ++ descriptor = getAppendDescriptor( ++ ElementProto$1, ++ "before", ++ isFrozenOrHasFrozenParent, ++ getSnippetDataFromNodeOrParent ++ ); ++ wrapPropertyAccess(ElementProto$1, "before", descriptor); ++ ++ descriptor = getInsertAdjacentDescriptor( ++ ElementProto$1, ++ "insertAdjacentElement", ++ isFrozenAndInsideTarget, ++ getSnippetDataBasedOnTarget ++ ); ++ wrapPropertyAccess(ElementProto$1, "insertAdjacentElement", descriptor); ++ ++ descriptor = getInsertAdjacentDescriptor( ++ ElementProto$1, ++ "insertAdjacentHTML", ++ isFrozenAndInsideTarget, ++ getSnippetDataBasedOnTarget ++ ); ++ wrapPropertyAccess(ElementProto$1, "insertAdjacentHTML", descriptor); ++ ++ descriptor = getInsertAdjacentDescriptor( ++ ElementProto$1, ++ "insertAdjacentText", ++ isFrozenAndInsideTarget, ++ getSnippetDataBasedOnTarget ++ ); ++ wrapPropertyAccess(ElementProto$1, "insertAdjacentText", descriptor); ++ ++ descriptor = getInnerHTMLDescriptor( ++ ElementProto$1, "innerHTML", isFrozen, getSnippetData ++ ); ++ wrapPropertyAccess(ElementProto$1, "innerHTML", descriptor); ++ ++ descriptor = getInnerHTMLDescriptor( ++ ElementProto$1, ++ "outerHTML", ++ isFrozenOrHasFrozenParent, ++ getSnippetDataFromNodeOrParent ++ ); ++ wrapPropertyAccess(ElementProto$1, "outerHTML", descriptor); ++ ++ descriptor = getTextContentDescriptor( ++ NodeProto, "textContent", isFrozen, getSnippetData ++ ); ++ wrapPropertyAccess(NodeProto, "textContent", descriptor); ++ ++ descriptor = getTextContentDescriptor( ++ HTMLElementProto, "innerText", isFrozen, getSnippetData ++ ); ++ wrapPropertyAccess(HTMLElementProto, "innerText", descriptor); ++ ++ descriptor = getTextContentDescriptor( ++ NodeProto, "nodeValue", isFrozen, getSnippetData ++ ); ++ wrapPropertyAccess(NodeProto, "nodeValue", descriptor); ++ ++ function isFrozen(node) { ++ return node && variables.frozen.has(node); ++ } ++ ++ function isFrozenOrHasFrozenParent(node) { ++ try { ++ return node && ++ (variables.frozen.has(node) || ++ variables.frozen.has($(node).parentNode)); ++ } ++ catch (error) { ++ return false; ++ } ++ } ++ ++ function isFrozenAndInsideTarget(node, isInsideTarget) { ++ try { ++ return node && ++ (variables.frozen.has(node) && isInsideTarget || ++ variables.frozen.has($(node).parentNode) && ++ !isInsideTarget); ++ } ++ catch (error) { ++ return false; ++ } ++ } ++ ++ function getSnippetData(node) { ++ return variables.frozen.get(node); ++ } ++ ++ function getSnippetDataFromNodeOrParent(node) { ++ try { ++ if (variables.frozen.has(node)) ++ return variables.frozen.get(node); ++ let parent = $(node).parentNode; ++ return variables.frozen.get(parent); ++ } ++ catch (error) {} ++ } ++ ++ function getSnippetDataBasedOnTarget(node, isInsideTarget) { ++ try { ++ if (variables.frozen.has(node) && isInsideTarget) ++ return variables.frozen.get(node); ++ let parent = $(node).parentNode; ++ return variables.frozen.get(parent); ++ } ++ catch (error) {} ++ } ++ } ++ ++ function searchAndAttach() { ++ targetNodes = queryAll(); ++ markNodes(targetNodes, false); ++ } ++ ++ function markNodes(nodes, isChild = true) { ++ for (let node of nodes) { ++ if (!variables.frozen.has(node)) { ++ variables.frozen.set(node, data); ++ if (!isChild && subtree) { ++ new MutationObserver$1(mutationsList => { ++ for (let mutation of $(mutationsList)) ++ markNodes($(mutation, "MutationRecord").addedNodes); ++ }).observe(node, {childList: true, subtree: true}); ++ } ++ if (subtree && $(node).nodeType === ELEMENT_NODE) ++ markNodes($(node).childNodes); ++ } ++ } ++ } ++ ++ function logPrefixed(id, ...args) { ++ log(`[freeze][${id}] `, ...args); ++ } ++ ++ function logChange(nodeOrDOMString, target, property, snippetData) { ++ let targetSelector = snippetData.selector; ++ let chgId = snippetData.changeId; ++ let isDOMString = typeof nodeOrDOMString == "string"; ++ let action = snippetData.shouldAbort ? "aborting" : "watching"; ++ console$2.groupCollapsed(`[freeze][${chgId}] ${action}: ${targetSelector}`); ++ switch (property) { ++ case "appendChild": ++ case "append": ++ case "prepend": ++ case "insertBefore": ++ case "replaceChild": ++ case "insertAdjacentElement": ++ case "insertAdjacentHTML": ++ case "insertAdjacentText": ++ case "innerHTML": ++ case "outerHTML": ++ logPrefixed(chgId, ++ isDOMString ? "text: " : "node: ", ++ nodeOrDOMString); ++ logPrefixed(chgId, "added to node: ", target); ++ break; ++ case "replaceWith": ++ case "after": ++ case "before": ++ logPrefixed(chgId, ++ isDOMString ? "text: " : "node: ", ++ nodeOrDOMString); ++ logPrefixed(chgId, "added to node: ", $(target).parentNode); ++ break; ++ case "textContent": ++ case "innerText": ++ case "nodeValue": ++ logPrefixed(chgId, "content of node: ", target); ++ logPrefixed(chgId, "changed to: ", nodeOrDOMString); ++ break; ++ } ++ logPrefixed(chgId, `using the function "${property}"`); ++ console$2.groupEnd(); ++ snippetData.changeId++; ++ } ++ ++ function isExceptionNode(element, expSelectors) { ++ if (expSelectors) { ++ let $element = $(element); ++ for (let exception of expSelectors) { ++ if ($element.matches(exception)) ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ function isExceptionText(string, regExceptions) { ++ if (regExceptions) { ++ for (let exception of regExceptions) { ++ if (exception.test(string)) ++ return true; ++ } ++ } ++ return false; ++ } ++ ++ function abort(id) { ++ throw new ReferenceError(id); ++ } ++ ++ function checkHTML(htmlText, parent, property, snippetData) { ++ let domparser = new DOMParser(); ++ let {body} = $(domparser.parseFromString(htmlText, "text/html")); ++ let nodes = $(body).childNodes; ++ let accepted = checkMultiple(nodes, parent, property, snippetData); ++ let content = $(accepted).map(node => { ++ switch ($(node).nodeType) { ++ case ELEMENT_NODE: ++ return $(node).outerHTML; ++ case TEXT_NODE: ++ return $(node).textContent; ++ default: ++ return ""; ++ } ++ }); ++ return content.join(""); ++ } ++ ++ function checkMultiple(nodesOrDOMStrings, parent, property, snippetData) { ++ let accepted = $([]); ++ for (let nodeOrDOMString of nodesOrDOMStrings) { ++ if (checkShouldInsert(nodeOrDOMString, parent, property, snippetData)) ++ accepted.push(nodeOrDOMString); ++ } ++ return accepted; ++ } ++ ++ function checkShouldInsert(nodeOrDOMString, parent, property, snippetData) { ++ let aborting = snippetData.shouldAbort; ++ let regExceptions = snippetData.regexExceptions; ++ let expSelectors = snippetData.exceptionSelectors; ++ let id = snippetData.rid; ++ if (typeof nodeOrDOMString == "string") { ++ let domString = nodeOrDOMString; ++ if (isExceptionText(domString, regExceptions)) ++ return true; ++ if (debug()) ++ logChange(domString, parent, property, snippetData); ++ if (aborting) ++ abort(id); ++ return debug(); ++ } ++ ++ let node = nodeOrDOMString; ++ switch ($(node).nodeType) { ++ case ELEMENT_NODE: ++ if (isExceptionNode(node, expSelectors)) ++ return true; ++ if (aborting) { ++ if (debug()) ++ logChange(node, parent, property, snippetData); ++ abort(id); ++ } ++ if (debug()) { ++ hideElement(node); ++ logChange(node, parent, property, snippetData); ++ return true; ++ } ++ return false; ++ case TEXT_NODE: ++ if (isExceptionText($(node).textContent, regExceptions)) ++ return true; ++ if (debug()) ++ logChange(node, parent, property, snippetData); ++ if (aborting) ++ abort(id); ++ return false; ++ default: ++ return true; ++ } ++ } ++ ++ function getAppendChildDescriptor(target, property, shouldValidate, ++ getSnippetData) { ++ let desc = getOwnPropertyDescriptor(target, property) || {}; ++ let origin = desc.get && call(desc.get, target) || desc.value; ++ if (!origin) ++ return; ++ ++ return { ++ get() { ++ return function(...args) { ++ if (shouldValidate(this)) { ++ let snippetData = getSnippetData(this); ++ if (snippetData) { ++ let incomingNode = args[0]; ++ if (!checkShouldInsert(incomingNode, this, property, snippetData)) ++ return incomingNode; ++ } ++ } ++ return apply$2(origin, this, args); ++ }; ++ } ++ }; ++ } ++ ++ function getAppendDescriptor( ++ target, property, shouldValidate, getSnippetData ++ ) { ++ let desc = getOwnPropertyDescriptor(target, property) || {}; ++ let origin = desc.get && call(desc.get, target) || desc.value; ++ if (!origin) ++ return; ++ return { ++ get() { ++ return function(...nodesOrDOMStrings) { ++ if (!shouldValidate(this)) ++ return apply$2(origin, this, nodesOrDOMStrings); ++ ++ let snippetData = getSnippetData(this); ++ if (!snippetData) ++ return apply$2(origin, this, nodesOrDOMStrings); ++ ++ let accepted = checkMultiple( ++ nodesOrDOMStrings, this, property, snippetData ++ ); ++ if (accepted.length > 0) ++ return apply$2(origin, this, accepted); ++ }; ++ } ++ }; ++ } ++ ++ function getInsertAdjacentDescriptor( ++ target, property, shouldValidate, getSnippetData ++ ) { ++ let desc = getOwnPropertyDescriptor(target, property) || {}; ++ let origin = desc.get && call(desc.get, target) || desc.value; ++ if (!origin) ++ return; ++ ++ return { ++ get() { ++ return function(...args) { ++ let [position, value] = args; ++ let isInsideTarget = ++ position === "afterbegin" || position === "beforeend"; ++ if (shouldValidate(this, isInsideTarget)) { ++ let snippetData = getSnippetData(this, isInsideTarget); ++ if (snippetData) { ++ let parent = isInsideTarget ? ++ this : ++ $(this).parentNode; ++ let finalValue; ++ switch (property) { ++ case "insertAdjacentElement": ++ if (!checkShouldInsert(value, parent, property, snippetData)) ++ return value; ++ break; ++ ++ case "insertAdjacentHTML": ++ finalValue = checkHTML(value, parent, property, snippetData); ++ if (finalValue) ++ return call(origin, this, position, finalValue); ++ ++ return; ++ ++ case "insertAdjacentText": ++ if (!checkShouldInsert(value, parent, property, snippetData)) ++ return; ++ break; ++ } ++ } ++ } ++ return apply$2(origin, this, args); ++ }; ++ } ++ }; ++ } ++ ++ function getInnerHTMLDescriptor( ++ target, property, shouldValidate, getSnippetData ++ ) { ++ let desc = getOwnPropertyDescriptor(target, property) || {}; ++ let {set: prevSetter} = desc; ++ if (!prevSetter) ++ return; ++ ++ return { ++ set(htmlText) { ++ if (!shouldValidate(this)) ++ return call(prevSetter, this, htmlText); ++ ++ let snippetData = getSnippetData(this); ++ if (!snippetData) ++ return call(prevSetter, this, htmlText); ++ let finalValue = checkHTML(htmlText, this, property, snippetData); ++ if (finalValue) ++ return call(prevSetter, this, finalValue); ++ } ++ }; ++ } ++ ++ function getTextContentDescriptor( ++ target, property, shouldValidate, getSnippetData ++ ) { ++ let desc = getOwnPropertyDescriptor(target, property) || {}; ++ let {set: prevSetter} = desc; ++ if (!prevSetter) ++ return; ++ ++ return { ++ set(domString) { ++ if (!shouldValidate(this)) ++ return call(prevSetter, this, domString); ++ ++ let snippetData = getSnippetData(this); ++ if (!snippetData) ++ return call(prevSetter, this, domString); ++ if (checkShouldInsert(domString, this, property, snippetData)) ++ return call(prevSetter, this, domString); ++ } ++ }; ++ } ++ } ++ ++ $(window); ++ ++ function raceWinner(name, lose) { ++ ++ return noop; ++ } ++ ++ const {Map: Map$4, MutationObserver, Object: Object$4, Set, WeakSet: WeakSet$1} = $(window); ++ ++ let ElementProto = Element.prototype; ++ let {attachShadow} = ElementProto; ++ ++ let hiddenShadowRoots = new WeakSet$1(); ++ let searches = new Map$4(); ++ let observer = null; ++ ++ function hideIfShadowContains(search, selector = "*") { ++ ++ let key = `${search}\\${selector}`; ++ if (!searches.has(key)) { ++ searches.set(key, [toRegExp(search), selector, raceWinner() ++ ]); ++ } ++ ++ if (!observer) { ++ observer = new MutationObserver(records => { ++ let visited = new Set(); ++ for (let {target} of $(records)) { ++ ++ let parent = $(target).parentNode; ++ while (parent) ++ [target, parent] = [parent, $(target).parentNode]; ++ ++ if (hiddenShadowRoots.has(target)) ++ continue; ++ ++ if (visited.has(target)) ++ continue; ++ ++ visited.add(target); ++ ++ for (let [re, selfOrParent, win] of searches.values()) { ++ if (re.test($(target).textContent)) { ++ let closest = $(target.host).closest(selfOrParent); ++ if (closest) { ++ win(); ++ ++ $(target).appendChild( ++ document.createElement("style") ++ ).textContent = ":host {display: none !important}"; ++ ++ hideElement(closest); ++ ++ hiddenShadowRoots.add(target); ++ } ++ } ++ } ++ } ++ }); ++ ++ Object$4.defineProperty(ElementProto, "attachShadow", { ++ ++ value: proxy(attachShadow, function() { ++ ++ let root = apply$2(attachShadow, this, arguments); ++ ++ observer.observe(root, { ++ childList: true, ++ characterData: true, ++ subtree: true ++ }); ++ ++ return root; ++ }) ++ }); ++ } ++ } ++ ++ const {Error: Error$4, JSON: JSON$2, Map: Map$3, Object: Object$3} = $(window); ++ ++ let paths$1 = null; ++ ++ function jsonOverride(rawOverridePaths, value, ++ rawNeedlePaths = "", filter = "") { ++ if (!rawOverridePaths) ++ throw new Error$4("[json-override snippet]: Missing paths to override."); ++ ++ if (typeof value == "undefined") ++ throw new Error$4("[json-override snippet]: No value to override with."); ++ ++ if (!paths$1) { ++ let debugLog = getDebugger("json-override"); ++ ++ let {parse} = JSON$2; ++ paths$1 = new Map$3(); ++ ++ Object$3.defineProperty(window.JSON, "parse", { ++ value: proxy(parse, function(str) { ++ let result = apply$2(parse, this, arguments); ++ ++ for (let {prune, needle, filter: flt, value: val} of paths$1.values()) { ++ if (flt && !flt.test(str)) ++ continue; ++ ++ if ($(needle).some(path => !findOwner(result, path))) ++ return result; ++ ++ for (let path of prune) { ++ let details = findOwner(result, path); ++ if (typeof details != "undefined") { ++ debugLog(`Found ${path} replaced it with ${val}`); ++ details[0][details[1]] = overrideValue(val); ++ } ++ } ++ } ++ ++ return result; ++ }) ++ }); ++ debugLog("Wrapped JSON.parse for override"); ++ } ++ ++ paths$1.set(rawOverridePaths, { ++ prune: $(rawOverridePaths).split(/ +/), ++ needle: rawNeedlePaths.length ? $(rawNeedlePaths).split(/ +/) : [], ++ filter: filter ? toRegExp(filter) : null, ++ value ++ }); ++ } ++ ++ let {Error: Error$3, JSON: JSON$1, Map: Map$2, Object: Object$2} = $(window); ++ ++ let paths = null; ++ ++ function jsonPrune(rawPrunePaths, rawNeedlePaths = "") { ++ if (!rawPrunePaths) ++ throw new Error$3("Missing paths to prune"); ++ ++ if (!paths) { ++ let debugLog = getDebugger("json-prune"); ++ ++ let {parse} = JSON$1; ++ paths = new Map$2(); ++ ++ Object$2.defineProperty(window.JSON, "parse", { ++ value: proxy(parse, function() { ++ let result = apply$2(parse, this, arguments); ++ ++ for (let {prune, needle} of paths.values()) { ++ if ($(needle).some(path => !findOwner(result, path))) ++ return result; ++ ++ for (let path of prune) { ++ let details = findOwner(result, path); ++ if (typeof details != "undefined") { ++ debugLog(`Found ${path} and deleted`); ++ delete details[0][details[1]]; ++ } ++ } ++ } ++ ++ return result; ++ }) ++ }); ++ debugLog("Wrapped JSON.parse for prune"); ++ } ++ ++ paths.set(rawPrunePaths, { ++ prune: $(rawPrunePaths).split(/ +/), ++ needle: rawNeedlePaths.length ? $(rawNeedlePaths).split(/ +/) : [] ++ }); ++ } ++ ++ let {Error: Error$2} = $(window); ++ ++ function overridePropertyRead(property, value) { ++ if (!property) { ++ throw new Error$2("[override-property-read snippet]: " + ++ "No property to override."); ++ } ++ if (typeof value === "undefined") { ++ throw new Error$2("[override-property-read snippet]: " + ++ "No value to override with."); ++ } ++ ++ let debugLog = getDebugger("override-property-read"); ++ ++ let cValue = overrideValue(value); ++ ++ let newGetter = () => { ++ debugLog(`${property} override done.`); ++ return cValue; ++ }; ++ ++ debugLog(`Overriding ${property}.`); ++ ++ wrapPropertyAccess(window, property, {get: newGetter, set() {}}); ++ } ++ ++ let {Error: Error$1, Map: Map$1, Object: Object$1, console: console$1} = $(window); ++ ++ let {toString} = Function.prototype; ++ let EventTargetProto = EventTarget.prototype; ++ let {addEventListener} = EventTargetProto; ++ ++ let events = null; ++ ++ function preventListener(event, eventHandler, selector) { ++ if (!event) ++ throw new Error$1("[prevent-listener snippet]: No event type."); ++ ++ if (!events) { ++ events = new Map$1(); ++ ++ let debugLog = getDebugger("[prevent]"); ++ ++ Object$1.defineProperty(EventTargetProto, "addEventListener", { ++ value: proxy(addEventListener, function(type, listener) { ++ for (let {evt, handlers, selectors} of events.values()) { ++ ++ if (!evt.test(type)) ++ continue; ++ ++ let isElement = this instanceof Element; ++ ++ for (let i = 0; i < handlers.length; i++) { ++ let handler = handlers[i]; ++ let sel = selectors[i]; ++ ++ let handlerMatch = () => handler.test( ++ call( ++ toString, ++ typeof listener === "function" ? ++ listener : listener.handleEvent ++ ) ++ ); ++ ++ if ( ++ (handler && !handlerMatch()) || ++ (sel && !(isElement && $(this).matches(sel))) ++ ) ++ continue; ++ ++ if (debug()) { ++ console$1.groupCollapsed("DEBUG [prevent] was successful"); ++ debugLog(`type: ${type} matching ${evt}`); ++ debugLog("handler:", listener); ++ if (handler) ++ debugLog(`matching ${handler}`); ++ if (sel) ++ debugLog("on element: ", this, ` matching ${sel}`); ++ debugLog("was prevented from being added"); ++ console$1.groupEnd(); ++ } ++ return; ++ } ++ } ++ return apply$2(addEventListener, this, arguments); ++ }) ++ }); ++ ++ debugLog("Wrapped addEventListener"); ++ } ++ ++ if (!events.has(event)) ++ events.set(event, {evt: toRegExp(event), handlers: [], selectors: []}); ++ ++ let {handlers, selectors} = events.get(event); ++ ++ handlers.push(eventHandler ? toRegExp(eventHandler) : null); ++ selectors.push(selector); ++ } ++ ++ let {URL, fetch} = $(window); ++ ++ let {delete: deleteParam} = caller(URLSearchParams.prototype); ++ ++ let parameters; ++ ++ function stripFetchQueryParameter(name, urlPattern = null) { ++ ++ if (!parameters) { ++ parameters = new Map(); ++ window.fetch = proxy(fetch, (...args) => { ++ let [source] = args; ++ if (typeof source === "string") { ++ let url = new URL(source); ++ for (let [key, reg] of parameters) { ++ if (!reg || reg.test(source)) { ++ deleteParam(url.searchParams, key); ++ args[0] = url.href; ++ } ++ } ++ } ++ return apply$2(fetch, self, args); ++ }); ++ } ++ ++ parameters.set(name, urlPattern && toRegExp(urlPattern)); ++ } ++ ++ function trace(...args) { ++ ++ apply$2(log, null, args); ++ } ++ ++ const snippets = { ++ "abort-current-inline-script": abortCurrentInlineScript, ++ "abort-on-iframe-property-read": abortOnIframePropertyRead, ++ "abort-on-iframe-property-write": abortOnIframePropertyWrite, ++ "abort-on-property-read": abortOnPropertyRead, ++ "abort-on-property-write": abortOnPropertyWrite, ++ "cookie-remover": cookieRemover, ++ "debug": setDebug, ++ "freeze-element": freezeElement, ++ "hide-if-shadow-contains": hideIfShadowContains, ++ "json-override": jsonOverride, ++ "json-prune": jsonPrune, ++ "override-property-read": overridePropertyRead, ++ "prevent-listener": preventListener, ++ "strip-fetch-query-parameter": stripFetchQueryParameter, ++ "trace": trace ++ }; ++ let context; ++ for (const [name, ...args] of filters) { ++ if (snippets.hasOwnProperty(name)) { ++ try { context = snippets[name].apply(context, args); } ++ catch (error) { console.error(error); } ++ } ++ } ++ context = void 0; ++}; ++const graph = new Map([["abort-current-inline-script",null],["abort-on-iframe-property-read",null],["abort-on-iframe-property-write",null],["abort-on-property-read",null],["abort-on-property-write",null],["cookie-remover",null],["debug",null],["freeze-element",null],["hide-if-shadow-contains",null],["json-override",null],["json-prune",null],["override-property-read",null],["prevent-listener",null],["strip-fetch-query-parameter",null],["trace",null]]); ++callback.get = snippet => graph.get(snippet); ++callback.has = snippet => graph.has(snippet); ++ ++ if (t.every(([name]) => !callback.has(name))) return; ++ const append = () => { ++ URL.revokeObjectURL( ++ Object.assign( ++ document.documentElement.appendChild(document.createElement("script")), ++ {async: false, src: URL.createObjectURL(new Blob([ ++ "(" + callback + ")(..." + JSON.stringify([e, ...t]) + ")" ++ ]))} ++ ).src ++ ); ++ }; ++ try { append(); } ++ catch (_) { ++ document.addEventListener("readystatechange", append, {once:true}); ++ } ++} +\ No newline at end of file +-- +2.25.1 diff --git a/build/patches/00Eyeo-Adblock.patch b/build/patches/00Eyeo-Adblock.patch new file mode 100644 index 00000000..bc330162 --- /dev/null +++ b/build/patches/00Eyeo-Adblock.patch @@ -0,0 +1,158138 @@ +From: Your Name +Date: Wed, 28 Sep 2022 13:30:51 +0000 +Subject: Eyeo Adblock + +--- + DEPS | 24 + + README.md | 12 + + base/trace_event/builtin_categories.h | 5 + + build/install-build-deps.sh | 12 +- + chrome/android/BUILD.gn | 8 + + .../android/chrome_common_shared_library.gni | 4 + + .../android/java/res/xml/main_preferences.xml | 21 +- + chrome/app/chrome_main_delegate.cc | 7 +- + chrome/browser/BUILD.gn | 35 + + chrome/browser/adblock/README.md | 3 + + .../adblock/adblock_content_browser_client.cc | 309 + + .../adblock/adblock_content_browser_client.h | 90 + + .../adblock/adblock_controller_factory.cc | 75 + + .../adblock/adblock_controller_factory.h | 50 + + .../adblock/adblock_debug_url_browsertest.cc | 116 + + ...ock_frame_hierarchy_builder_browsertest.cc | 119 + + .../adblock/adblock_mojo_interface_impl.cc | 267 + + .../adblock/adblock_mojo_interface_impl.h | 86 + + .../adblock_mojo_interface_impl_unittest.cc | 605 + + .../adblock_telemetry_service_factory.cc | 91 + + .../adblock_telemetry_service_factory.h | 50 + + ...ontent_security_policy_injector_factory.cc | 69 + + ...content_security_policy_injector_factory.h | 49 + + .../browser/adblock/element_hider_factory.cc | 63 + + .../browser/adblock/element_hider_factory.h | 47 + + .../resource_classification_runner_factory.cc | 71 + + .../resource_classification_runner_factory.h | 49 + + .../browser/adblock/session_stats_factory.cc | 64 + + .../browser/adblock/session_stats_factory.h | 47 + + .../adblock/sitekey_storage_factory.cc | 59 + + .../browser/adblock/sitekey_storage_factory.h | 47 + + ...ubscription_persistent_metadata_factory.cc | 63 + + ...subscription_persistent_metadata_factory.h | 49 + + .../adblock/subscription_service_factory.cc | 146 + + .../adblock/subscription_service_factory.h | 48 + + .../adblock/subscription_updater_factory.cc | 83 + + .../adblock/subscription_updater_factory.h | 50 + + chrome/browser/android/adblock/adblock_jni.cc | 568 + + chrome/browser/android/adblock/adblock_jni.h | 74 + + .../android/adblock/adblock_jni_factory.cc | 75 + + .../android/adblock/adblock_jni_factory.h | 50 + + .../chrome_autocomplete_provider_client.cc | 5 + + .../client_hints/client_hints_browsertest.cc | 12 +- + chrome/browser/extensions/BUILD.gn | 7 + + chrome/browser/extensions/api/BUILD.gn | 5 + + .../adblock_private/adblock_private_api.cc | 705 + + .../api/adblock_private/adblock_private_api.h | 412 + + .../adblock_private_apitest.cc | 469 + + .../api/settings_private/prefs_util.cc | 19 + + ...browser_context_keyed_service_factories.cc | 6 + + ..._page_load_metrics_observer_browsertest.cc | 7 +- + ...tifications_engagement_service_unittest.cc | 3 +- + chrome/browser/preferences/BUILD.gn | 5 + + .../prefs/chrome_command_line_pref_store.cc | 10 + + .../prefs/chrome_pref_service_factory.cc | 11 + + ...hrome_browser_main_extra_parts_profiles.cc | 22 + + .../profile_keyed_service_browsertest.cc | 331 +- + chrome/browser/resources/settings/BUILD.gn | 5 + + .../settings/adblock_page/adblock_page.html | 186 + + .../settings/adblock_page/adblock_page.ts | 317 + + .../settings/basic_page/basic_page.html | 7 + + .../settings/basic_page/basic_page.ts | 5 + + .../resources/settings/page_visibility.ts | 7 + + chrome/browser/resources/settings/route.ts | 9 + + chrome/browser/resources/settings/settings.ts | 6 +- + .../settings/settings_menu/settings_menu.html | 7 + + .../resources/settings/settings_routes.ts | 5 + + .../safe_browsing_blocking_page_test.cc | 8 +- + ...subresource_filter_browser_test_harness.cc | 10 +- + chrome/browser/ui/BUILD.gn | 5 + + chrome/browser/ui/prefs/pref_watcher.cc | 13 + + chrome/browser/ui/tab_helpers.cc | 20 + + chrome/common/BUILD.gn | 3 + + .../common/extensions/api/_api_features.json | 14 + + .../extensions/api/_permission_features.json | 8 + + .../common/extensions/api/adblock_private.idl | 168 + + chrome/common/extensions/api/api_sources.gni | 5 + + .../permissions/chrome_api_permissions.cc | 6 + + .../permissions/permission_set_unittest.cc | 7 + + chrome/common/webui_url_constants.cc | 5 + + chrome/common/webui_url_constants.h | 5 + + chrome/test/BUILD.gn | 18 + + chrome/test/base/chrome_test_launcher.cc | 7 +- + chrome/test/base/in_process_browser_test.cc | 17 +- + chrome/test/data/adblock/innermost_frame.html | 20 + + chrome/test/data/adblock/middle_frame.html | 8 + + chrome/test/data/adblock/outermost_frame.html | 20 + + chrome/test/data/adblock/resource.png | Bin 0 -> 47293 bytes + .../api_test/adblock_private/empty.js | 0 + .../api_test/adblock_private/main.html | 29 + + .../api_test/adblock_private/manifest.json | 27 + + .../api_test/adblock_private/test.html | 8 + + .../api_test/adblock_private/test.js | 468 + + components/BUILD.gn | 12 + + components/adblock/CHANGELOG.md | 489 + + components/adblock/LICENSE | 674 + + components/adblock/README.md | 80 + + components/adblock/android/BUILD.gn | 146 + + .../adblock/android/adblock_strings.grd | 237 + + .../fragment_adblock_custom_item_add.png | Bin 0 -> 490 bytes + .../fragment_adblock_custom_item_remove.png | Bin 0 -> 296 bytes + .../fragment_adblock_custom_item_add.png | Bin 0 -> 321 bytes + .../fragment_adblock_custom_item_remove.png | Bin 0 -> 169 bytes + .../fragment_adblock_custom_item_add.png | Bin 0 -> 1522 bytes + .../fragment_adblock_custom_item_remove.png | Bin 0 -> 696 bytes + .../fragment_adblock_custom_item_add.png | Bin 0 -> 747 bytes + .../fragment_adblock_custom_item_remove.png | Bin 0 -> 194 bytes + .../fragment_adblock_custom_item_add.png | Bin 0 -> 1485 bytes + .../fragment_adblock_custom_item_remove.png | Bin 0 -> 284 bytes + .../fragment_adblock_custom_item_add.png | Bin 0 -> 3393 bytes + .../fragment_adblock_custom_item_remove.png | Bin 0 -> 600 bytes + .../fragment_adblock_custom_item_add.png | Bin 0 -> 638 bytes + .../fragment_adblock_custom_item_remove.png | Bin 0 -> 240 bytes + .../fragment_adblock_custom_item_add.png | Bin 0 -> 933 bytes + .../fragment_adblock_custom_item_remove.png | Bin 0 -> 456 bytes + .../java/res/layout/adblock_custom_item.xml | 50 + + .../layout/adblock_custom_item_settings.xml | 65 + + .../layout/adblock_filter_lists_list_item.xml | 36 + + .../adblock_settings_locales_titles.xml | 98 + + .../java/res/xml/adblock_more_options.xml | 34 + + .../java/res/xml/adblock_preferences.xml | 63 + + ...blockComposeFilterSuggestionsCallback.java | 29 + + .../adblock/AdblockContentType.java | 62 + + .../components/adblock/AdblockController.java | 576 + + .../components/adblock/AdblockCounters.java | 86 + + .../components/adblock/AdblockElement.java | 85 + + .../AdblockAllowedDomainsFragment.java | 77 + + .../AdblockCustomFilterListsFragment.java | 97 + + .../AdblockCustomFiltersFragment.java | 76 + + .../settings/AdblockCustomItemFragment.java | 166 + + .../settings/AdblockFilterListsAdapter.java | 114 + + .../settings/AdblockFilterListsFragment.java | 54 + + .../settings/AdblockMoreOptionsFragment.java | 34 + + .../settings/AdblockSettingsFragment.java | 156 + + .../adblock/AdblockControllerTest.java | 132 + + .../adblock/AdblockFilterFragmentTest.java | 73 + + .../adblock/AdblockPopupInfoBarTest.java | 127 + + .../adblock/AdblockPopupMessageTest.java | 112 + + .../adblock/TestPagesCircumventionTest.java | 89 + + .../components/adblock/TestPagesCspTest.java | 123 + + .../adblock/TestPagesElemhideEmuInvTest.java | 140 + + .../adblock/TestPagesElemhideEmuTest.java | 190 + + .../adblock/TestPagesElemhideTest.java | 214 + + .../adblock/TestPagesExceptionTest.java | 216 + + .../adblock/TestPagesFilterTest.java | 280 + + .../adblock/TestPagesHeaderFilterTest.java | 126 + + .../adblock/TestPagesRewriteTest.java | 157 + + .../adblock/TestPagesSiteKeyTest.java | 79 + + .../adblock/TestPagesSnippetsTest.java | 467 + + .../adblock/TestPagesTestsHelper.java | 406 + + .../adblock/TestPagesWebsocketTest.java | 79 + + .../translations/adblock_strings_af.xtb | 4 + + .../translations/adblock_strings_am.xtb | 14 + + .../translations/adblock_strings_ar.xtb | 17 + + .../translations/adblock_strings_as.xtb | 4 + + .../translations/adblock_strings_az.xtb | 4 + + .../translations/adblock_strings_be.xtb | 4 + + .../translations/adblock_strings_bg.xtb | 17 + + .../translations/adblock_strings_bn.xtb | 14 + + .../translations/adblock_strings_bs.xtb | 14 + + .../translations/adblock_strings_ca.xtb | 14 + + .../translations/adblock_strings_cs.xtb | 14 + + .../translations/adblock_strings_da.xtb | 14 + + .../translations/adblock_strings_de.xtb | 17 + + .../translations/adblock_strings_el.xtb | 17 + + .../translations/adblock_strings_en-GB.xtb | 16 + + .../translations/adblock_strings_es-419.xtb | 17 + + .../translations/adblock_strings_es.xtb | 17 + + .../translations/adblock_strings_et.xtb | 14 + + .../translations/adblock_strings_eu.xtb | 4 + + .../translations/adblock_strings_fa.xtb | 14 + + .../translations/adblock_strings_fi.xtb | 14 + + .../translations/adblock_strings_fil.xtb | 14 + + .../translations/adblock_strings_fr-CA.xtb | 16 + + .../translations/adblock_strings_fr.xtb | 16 + + .../translations/adblock_strings_gl.xtb | 4 + + .../translations/adblock_strings_gu.xtb | 4 + + .../translations/adblock_strings_hi.xtb | 14 + + .../translations/adblock_strings_hr.xtb | 14 + + .../translations/adblock_strings_hu.xtb | 17 + + .../translations/adblock_strings_hy.xtb | 4 + + .../translations/adblock_strings_id.xtb | 14 + + .../translations/adblock_strings_is.xtb | 4 + + .../translations/adblock_strings_it.xtb | 17 + + .../translations/adblock_strings_iw.xtb | 14 + + .../translations/adblock_strings_ja.xtb | 17 + + .../translations/adblock_strings_ka.xtb | 4 + + .../translations/adblock_strings_kk.xtb | 14 + + .../translations/adblock_strings_km.xtb | 14 + + .../translations/adblock_strings_kn.xtb | 4 + + .../translations/adblock_strings_ko.xtb | 17 + + .../translations/adblock_strings_ky.xtb | 4 + + .../translations/adblock_strings_lo.xtb | 4 + + .../translations/adblock_strings_lt.xtb | 14 + + .../translations/adblock_strings_lv.xtb | 14 + + .../translations/adblock_strings_mk.xtb | 14 + + .../translations/adblock_strings_ml.xtb | 4 + + .../translations/adblock_strings_mn.xtb | 4 + + .../translations/adblock_strings_mr.xtb | 4 + + .../translations/adblock_strings_ms.xtb | 14 + + .../translations/adblock_strings_my.xtb | 14 + + .../translations/adblock_strings_ne.xtb | 4 + + .../translations/adblock_strings_nl.xtb | 17 + + .../translations/adblock_strings_no.xtb | 4 + + .../translations/adblock_strings_or.xtb | 4 + + .../translations/adblock_strings_pa.xtb | 4 + + .../translations/adblock_strings_pl.xtb | 17 + + .../translations/adblock_strings_pt-BR.xtb | 17 + + .../translations/adblock_strings_pt-PT.xtb | 15 + + .../translations/adblock_strings_ro.xtb | 14 + + .../translations/adblock_strings_ru.xtb | 17 + + .../translations/adblock_strings_si.xtb | 4 + + .../translations/adblock_strings_sk.xtb | 14 + + .../translations/adblock_strings_sl.xtb | 14 + + .../translations/adblock_strings_sq.xtb | 4 + + .../translations/adblock_strings_sr-Latn.xtb | 4 + + .../translations/adblock_strings_sr.xtb | 14 + + .../translations/adblock_strings_sv.xtb | 14 + + .../translations/adblock_strings_sw.xtb | 14 + + .../translations/adblock_strings_ta.xtb | 4 + + .../translations/adblock_strings_te.xtb | 4 + + .../translations/adblock_strings_th.xtb | 14 + + .../translations/adblock_strings_tr.xtb | 17 + + .../translations/adblock_strings_uk.xtb | 14 + + .../translations/adblock_strings_ur.xtb | 14 + + .../translations/adblock_strings_uz.xtb | 4 + + .../translations/adblock_strings_vi.xtb | 14 + + .../translations/adblock_strings_zh-CN.xtb | 17 + + .../translations/adblock_strings_zh-HK.xtb | 4 + + .../translations/adblock_strings_zh-TW.xtb | 14 + + .../translations/adblock_strings_zu.xtb | 4 + + components/adblock/content/BUILD.gn | 32 + + components/adblock/content/browser/BUILD.gn | 98 + + .../content/browser/adblock_content_utils.cc | 115 + + .../content/browser/adblock_content_utils.h | 33 + + .../browser/adblock_webcontents_observer.cc | 118 + + .../browser/adblock_webcontents_observer.h | 73 + + .../content_security_policy_injector.h | 60 + + .../content_security_policy_injector_impl.cc | 124 + + .../content_security_policy_injector_impl.h | 65 + + .../adblock/content/browser/element_hider.h | 70 + + .../content/browser/element_hider_impl.cc | 334 + + .../content/browser/element_hider_impl.h | 61 + + .../browser/frame_hierarchy_builder.cc | 90 + + .../content/browser/frame_hierarchy_builder.h | 64 + + .../browser/resource_classification_runner.h | 102 + + .../resource_classification_runner_impl.cc | 418 + + .../resource_classification_runner_impl.h | 157 + + .../content/browser/session_stats_impl.cc | 86 + + .../content/browser/session_stats_impl.h | 69 + + .../test/adblock_content_utils_test.cc | 113 + + .../test/adblock_webcontents_observer_test.cc | 135 + + ...tent_security_policy_injector_impl_test.cc | 236 + + .../browser/test/element_hider_impl_test.cc | 206 + + .../test/frame_hierarchy_builder_test.cc | 153 + + ...dblock_content_security_policy_injector.cc | 28 + + ...adblock_content_security_policy_injector.h | 44 + + .../browser/test/mock_element_hider.cc | 26 + + .../content/browser/test/mock_element_hider.h | 55 + + .../test/mock_frame_hierarchy_builder.cc | 26 + + .../test/mock_frame_hierarchy_builder.h | 49 + + .../mock_resource_classification_runner.cc | 26 + + .../mock_resource_classification_runner.h | 91 + + ...esource_classification_runner_impl_test.cc | 411 + + .../browser/test/session_stats_impl_test.cc | 162 + + components/adblock/content/common/BUILD.gn | 56 + + .../common/adblock_url_loader_factory.cc | 421 + + .../common/adblock_url_loader_factory.h | 73 + + .../adblock_url_loader_factory_for_test.cc | 196 + + .../adblock_url_loader_factory_for_test.h | 73 + + .../adblock/content/common/mojom/BUILD.gn | 26 + + .../content/common/mojom/adblock.mojom | 60 + + .../test/mock_adblock_mojo_interface.cc | 25 + + .../common/test/mock_adblock_mojo_interface.h | 61 + + components/adblock/core/BUILD.gn | 211 + + .../activeping_telemetry_topic_provider.cc | 206 + + .../activeping_telemetry_topic_provider.h | 72 + + components/adblock/core/adblock_controller.h | 80 + + .../adblock/core/adblock_controller_impl.cc | 466 + + .../adblock/core/adblock_controller_impl.h | 121 + + components/adblock/core/adblock_switches.cc | 27 + + components/adblock/core/adblock_switches.h | 30 + + .../adblock/core/adblock_telemetry_service.cc | 216 + + .../adblock/core/adblock_telemetry_service.h | 96 + + components/adblock/core/classifier/BUILD.gn | 77 + + .../core/classifier/resource_classifier.cc | 24 + + .../core/classifier/resource_classifier.h | 82 + + .../classifier/resource_classifier_impl.cc | 221 + + .../classifier/resource_classifier_impl.h | 67 + + .../test/mock_resource_classifier.cc | 26 + + .../test/mock_resource_classifier.h | 58 + + .../test/resource_classifier_impl_test.cc | 439 + + .../test/resource_classifier_perftest.cc | 219 + + components/adblock/core/common/BUILD.gn | 87 + + .../adblock/core/common/adblock_constants.cc | 170 + + .../adblock/core/common/adblock_constants.h | 43 + + .../adblock/core/common/adblock_prefs.cc | 127 + + .../adblock/core/common/adblock_prefs.h | 47 + + .../adblock/core/common/adblock_utils.cc | 167 + + .../adblock/core/common/adblock_utils.h | 81 + + .../core/common/allowed_connection_type.cc | 45 + + .../core/common/allowed_connection_type.h | 48 + + .../adblock/core/common/content_type.cc | 55 + + components/adblock/core/common/content_type.h | 46 + + .../adblock/core/common/converter_result.cc | 27 + + .../adblock/core/common/converter_result.h | 42 + + .../adblock/core/common/flatbuffer_data.cc | 90 + + .../adblock/core/common/flatbuffer_data.h | 85 + + .../adblock/core/common/header_filter_data.h | 38 + + .../core/common/keyword_extractor_utils.cc | 29 + + .../core/common/keyword_extractor_utils.h | 31 + + components/adblock/core/common/sitekey.h | 29 + + .../core/common/test/adblock_utils_test.cc | 43 + + .../core/common/test/flatbuffer_data_test.cc | 78 + + components/adblock/core/converter/BUILD.gn | 96 + + .../adblock/core/converter/converter.cc | 1029 + + components/adblock/core/converter/converter.h | 108 + + .../core/converter/converter_standalone.cc | 85 + + .../converter/filter_keyword_extractor.cc | 62 + + .../core/converter/filter_keyword_extractor.h | 62 + + components/adblock/core/converter/metadata.cc | 157 + + components/adblock/core/converter/metadata.h | 67 + + .../core/converter/snippet_tokenizer.h | 36 + + .../core/converter/snippet_tokenizer_impl.cc | 100 + + .../core/converter/snippet_tokenizer_impl.h | 49 + + .../core/converter/test/converter_perftest.cc | 60 + + .../core/converter/test/converter_test.cc | 2126 + + .../test/filter_keyword_extractor_test.cc | 69 + + .../core/converter/test/metadata_test.cc | 195 + + .../converter/test/mock_snippet_tokenizer.cc | 26 + + .../converter/test/mock_snippet_tokenizer.h | 43 + + .../test/snippet_tokenizer_impl_test.cc | 134 + + components/adblock/core/features.cc | 25 + + components/adblock/core/features.gni | 46 + + components/adblock/core/features.h | 31 + + .../core/schema/filter_list_schema.fbs | 166 + + components/adblock/core/session_stats.h | 44 + + components/adblock/core/sitekey_storage.h | 53 + + .../adblock/core/sitekey_storage_impl.cc | 144 + + .../adblock/core/sitekey_storage_impl.h | 59 + + components/adblock/core/subscription/BUILD.gn | 120 + + .../core/subscription/domain_splitter.cc | 45 + + .../core/subscription/domain_splitter.h | 45 + + .../subscription/installed_subscription.cc | 42 + + .../subscription/installed_subscription.h | 139 + + .../installed_subscription_impl.cc | 643 + + .../installed_subscription_impl.h | 174 + + .../ongoing_subscription_request.h | 50 + + .../ongoing_subscription_request_impl.cc | 238 + + .../ongoing_subscription_request_impl.h | 81 + + .../preloaded_subscription_provider.h | 56 + + .../preloaded_subscription_provider_impl.cc | 141 + + .../preloaded_subscription_provider_impl.h | 56 + + .../adblock/core/subscription/subscription.cc | 24 + + .../adblock/core/subscription/subscription.h | 76 + + .../subscription/subscription_collection.h | 93 + + .../subscription_collection_impl.cc | 384 + + .../subscription_collection_impl.h | 91 + + .../core/subscription/subscription_config.cc | 300 + + .../core/subscription/subscription_config.h | 113 + + .../subscription/subscription_downloader.h | 66 + + .../subscription_downloader_impl.cc | 289 + + .../subscription_downloader_impl.h | 106 + + .../subscription_persistent_metadata.h | 86 + + .../subscription_persistent_metadata_impl.cc | 166 + + .../subscription_persistent_metadata_impl.h | 61 + + .../subscription_persistent_storage.h | 60 + + .../subscription_persistent_storage_impl.cc | 225 + + .../subscription_persistent_storage_impl.h | 77 + + .../core/subscription/subscription_service.h | 81 + + .../subscription/subscription_service_impl.cc | 405 + + .../subscription/subscription_service_impl.h | 115 + + .../core/subscription/subscription_updater.h | 33 + + .../subscription/subscription_updater_impl.cc | 140 + + .../subscription/subscription_updater_impl.h | 66 + + .../subscription/subscription_validator.cc | 24 + + .../subscription/subscription_validator.h | 54 + + .../subscription_validator_impl.cc | 125 + + .../subscription_validator_impl.h | 56 + + .../test/installed_subscription_impl_test.cc | 74 + + .../test/mock_installed_subscription.cc | 26 + + .../test/mock_installed_subscription.h | 99 + + .../subscription/test/mock_subscription.cc | 36 + + .../subscription/test/mock_subscription.h | 49 + + .../test/mock_subscription_collection.cc | 26 + + .../test/mock_subscription_collection.h | 94 + + .../test/mock_subscription_downloader.cc | 25 + + .../test/mock_subscription_downloader.h | 46 + + .../mock_subscription_persistent_metadata.cc | 27 + + .../mock_subscription_persistent_metadata.h | 74 + + .../test/mock_subscription_service.cc | 25 + + .../test/mock_subscription_service.h | 62 + + .../test/mock_subscription_updater.cc | 25 + + .../test/mock_subscription_updater.h | 36 + + .../ongoing_subscription_request_impl_test.cc | 487 + + ...eloaded_subscription_provider_impl_test.cc | 231 + + .../test/subscription_collection_impl_test.cc | 839 + + .../test/subscription_downloader_impl_test.cc | 590 + + ...scription_persistent_metadata_impl_test.cc | 213 + + ...bscription_persistent_storage_impl_test.cc | 311 + + .../test/subscription_service_impl_test.cc | 854 + + .../test/subscription_updater_impl_test.cc | 330 + + .../test/subscription_validator_impl_test.cc | 180 + + .../test/url_keyword_extractor_test.cc | 74 + + .../subscription/url_keyword_extractor.cc | 59 + + .../core/subscription/url_keyword_extractor.h | 61 + + ...ctiveping_telemetry_topic_provider_test.cc | 310 + + .../core/test/adblock_controller_impl_test.cc | 818 + + .../adblock_telemetry_service_unittest.cc | 314 + + .../core/test/bundled_subscription_test.cc | 49 + + .../core/test/mock_adblock_controller.cc | 33 + + .../core/test/mock_adblock_controller.h | 85 + + .../adblock/core/test/mock_sitekey_storage.cc | 26 + + .../adblock/core/test/mock_sitekey_storage.h | 49 + + .../core/test/sitekey_storage_impl_test.cc | 131 + + .../adblock/docs/ad-filtering/README.md | 9 + + .../ad-filtering/element-hiding-sequence.png | Bin 0 -> 177168 bytes + .../ad-filtering/element-hiding-sequence.txt | 32 + + .../docs/ad-filtering/element-hiding.md | 11 + + .../adblock/docs/ad-filtering/filter-lists.md | 42 + + .../request-filter-matching-sequence.png | Bin 0 -> 191937 bytes + .../request_filter_matching_sequence.txt | 33 + + .../docs/ad-filtering/resource-filtering.md | 30 + + .../response-filter-matching-sequence.png | Bin 0 -> 212826 bytes + .../response_filter_matching_sequence.txt | 35 + + .../adblock/docs/ad-filtering/snippets.md | 7 + + components/adblock/docs/adr/README.md | 3 + + .../docs/adr/consuming-full-filter-lists.md | 8 + + ...ving-user-counting-to-dedicated-service.md | 5 + + .../adr/not-extending-subresource-filter.md | 13 + + ...ring-filter-lists-in-flatbuffers-format.md | 17 + + .../adblock/docs/data-collection/README.md | 11 + + .../docs/data-collection/user-counting.md | 38 + + components/adblock/docs/design-overview.md | 31 + + components/adblock/docs/developer-notes.md | 117 + + .../adblock/docs/initialization-sequence.png | Bin 0 -> 129976 bytes + .../adblock/docs/initialization-sequence.txt | 27 + + components/adblock/docs/integration-how-to.md | 224 + + components/adblock/docs/settings/README.md | 35 + + .../docs/settings/user-setting-sequence.png | Bin 0 -> 63401 bytes + .../docs/settings/user-setting-sequence.txt | 14 + + components/adblock_comparison/BUILD.gn | 47 + + .../libadblockplus_reference_database.cc | 236 + + .../libadblockplus_reference_database.h | 98 + + .../adblock_comparison/test_request_reader.cc | 109 + + .../adblock_comparison/test_request_reader.h | 54 + + .../verify_flatbuffer_adblocking.cc | 263 + + components/resources/BUILD.gn | 9 + + components/resources/adblock_resources.grdp | 23 + + components/resources/adblocking/.gitignore | 1 + + components/resources/adblocking/BUILD.gn | 70 + + components/resources/adblocking/anticv.txt | 2392 + + components/resources/adblocking/easylist.txt | 10449 +++ + components/resources/adblocking/elemhide.js | 43 + + .../adblocking/elemhide_for_selector.jst | 53 + + .../resources/adblocking/elemhideemu.jst | 1436 + + .../resources/adblocking/exceptionrules.txt | 5661 ++ + components/resources/adblocking/update.sh | 30 + + components/resources/components_resources.grd | 1 + + components/test/data/adblock/anticv.txt | 1317 + + components/test/data/adblock/easylist.txt | 56515 ++++++++++++++++ + .../test/data/adblock/exceptionrules.txt | 17738 +++++ + components/test/data/adblock/longurl.txt | 1 + + .../data/adblock/random_shuf_100.tsv.sqlite | Bin 0 -> 40960 bytes + components/variations/service/BUILD.gn | 4 + + .../loader/navigation_url_loader_impl.cc | 6 +- + .../renderer_host/render_frame_host_impl.cc | 11 +- + .../renderer_host/render_frame_host_impl.h | 8 + + content/public/browser/render_frame_host.h | 7 + + content/public/common/isolated_world_ids.h | 8 + + content/public/test/fake_local_frame.cc | 7 + + content/public/test/fake_local_frame.h | 5 + + content/renderer/render_frame_impl.h | 4 + + ...web_request_proxying_url_loader_factory.cc | 5 + + .../browser/extension_event_histogram_value.h | 13 + + .../extension_function_histogram_value.h | 27 + + .../common/mojom/api_permission_id.mojom | 5 + + gclient/.gclient | 25 + + gclient/.gclient_ci_android | 22 + + gclient/.gclient_ci_linux | 21 + + gclient/.gclient_ci_windows | 22 + + net/url_request/redirect_info.cc | 4 + + net/url_request/redirect_info.h | 8 + + .../network/public/cpp/net_ipc_param_traits.h | 5 + + .../blink/public/mojom/frame/frame.mojom | 8 + + third_party/blink/public/web/web_document.h | 12 + + .../renderer/core/exported/web_document.cc | 52 + + .../core/frame/local_frame_mojo_handler.cc | 13 + + .../core/frame/local_frame_mojo_handler.h | 5 + + .../url_loader/mojo_url_loader_client.cc | 6 +- + tools/adblock/interdiff.py | 87 + + tools/metrics/histograms/enums.xml | 32 + + tools/perf/benchmarks/eyeo.py | 1193 + + tools/perf/page_sets/eyeo_page_set.py | 988 + + 494 files changed, 140674 insertions(+), 23 deletions(-) + create mode 100644 chrome/browser/adblock/README.md + create mode 100644 chrome/browser/adblock/adblock_content_browser_client.cc + create mode 100644 chrome/browser/adblock/adblock_content_browser_client.h + create mode 100644 chrome/browser/adblock/adblock_controller_factory.cc + create mode 100644 chrome/browser/adblock/adblock_controller_factory.h + create mode 100644 chrome/browser/adblock/adblock_debug_url_browsertest.cc + create mode 100644 chrome/browser/adblock/adblock_frame_hierarchy_builder_browsertest.cc + create mode 100644 chrome/browser/adblock/adblock_mojo_interface_impl.cc + create mode 100644 chrome/browser/adblock/adblock_mojo_interface_impl.h + create mode 100644 chrome/browser/adblock/adblock_mojo_interface_impl_unittest.cc + create mode 100644 chrome/browser/adblock/adblock_telemetry_service_factory.cc + create mode 100644 chrome/browser/adblock/adblock_telemetry_service_factory.h + create mode 100644 chrome/browser/adblock/content_security_policy_injector_factory.cc + create mode 100644 chrome/browser/adblock/content_security_policy_injector_factory.h + create mode 100644 chrome/browser/adblock/element_hider_factory.cc + create mode 100644 chrome/browser/adblock/element_hider_factory.h + create mode 100644 chrome/browser/adblock/resource_classification_runner_factory.cc + create mode 100644 chrome/browser/adblock/resource_classification_runner_factory.h + create mode 100644 chrome/browser/adblock/session_stats_factory.cc + create mode 100644 chrome/browser/adblock/session_stats_factory.h + create mode 100644 chrome/browser/adblock/sitekey_storage_factory.cc + create mode 100644 chrome/browser/adblock/sitekey_storage_factory.h + create mode 100644 chrome/browser/adblock/subscription_persistent_metadata_factory.cc + create mode 100644 chrome/browser/adblock/subscription_persistent_metadata_factory.h + create mode 100644 chrome/browser/adblock/subscription_service_factory.cc + create mode 100644 chrome/browser/adblock/subscription_service_factory.h + create mode 100644 chrome/browser/adblock/subscription_updater_factory.cc + create mode 100644 chrome/browser/adblock/subscription_updater_factory.h + create mode 100644 chrome/browser/android/adblock/adblock_jni.cc + create mode 100644 chrome/browser/android/adblock/adblock_jni.h + 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/extensions/api/adblock_private/adblock_private_api.cc + create mode 100644 chrome/browser/extensions/api/adblock_private/adblock_private_api.h + create mode 100644 chrome/browser/extensions/api/adblock_private/adblock_private_apitest.cc + create mode 100644 chrome/browser/resources/settings/adblock_page/adblock_page.html + create mode 100644 chrome/browser/resources/settings/adblock_page/adblock_page.ts + create mode 100644 chrome/common/extensions/api/adblock_private.idl + create mode 100644 chrome/test/data/adblock/innermost_frame.html + create mode 100644 chrome/test/data/adblock/middle_frame.html + create mode 100644 chrome/test/data/adblock/outermost_frame.html + create mode 100644 chrome/test/data/adblock/resource.png + create mode 100644 chrome/test/data/extensions/api_test/adblock_private/empty.js + create mode 100644 chrome/test/data/extensions/api_test/adblock_private/main.html + create mode 100644 chrome/test/data/extensions/api_test/adblock_private/manifest.json + create mode 100644 chrome/test/data/extensions/api_test/adblock_private/test.html + create mode 100644 chrome/test/data/extensions/api_test/adblock_private/test.js + create mode 100644 components/adblock/CHANGELOG.md + create mode 100644 components/adblock/LICENSE + create mode 100644 components/adblock/README.md + create mode 100644 components/adblock/android/BUILD.gn + create mode 100644 components/adblock/android/adblock_strings.grd + create mode 100644 components/adblock/android/java/res/drawable-hdpi/fragment_adblock_custom_item_add.png + create mode 100644 components/adblock/android/java/res/drawable-hdpi/fragment_adblock_custom_item_remove.png + create mode 100644 components/adblock/android/java/res/drawable-mdpi/fragment_adblock_custom_item_add.png + create mode 100644 components/adblock/android/java/res/drawable-mdpi/fragment_adblock_custom_item_remove.png + create mode 100644 components/adblock/android/java/res/drawable-night-hdpi/fragment_adblock_custom_item_add.png + create mode 100644 components/adblock/android/java/res/drawable-night-hdpi/fragment_adblock_custom_item_remove.png + create mode 100644 components/adblock/android/java/res/drawable-night-mdpi/fragment_adblock_custom_item_add.png + create mode 100644 components/adblock/android/java/res/drawable-night-mdpi/fragment_adblock_custom_item_remove.png + create mode 100644 components/adblock/android/java/res/drawable-night-xhdpi/fragment_adblock_custom_item_add.png + create mode 100644 components/adblock/android/java/res/drawable-night-xhdpi/fragment_adblock_custom_item_remove.png + create mode 100644 components/adblock/android/java/res/drawable-night-xxhdpi/fragment_adblock_custom_item_add.png + create mode 100644 components/adblock/android/java/res/drawable-night-xxhdpi/fragment_adblock_custom_item_remove.png + create mode 100644 components/adblock/android/java/res/drawable-xhdpi/fragment_adblock_custom_item_add.png + create mode 100644 components/adblock/android/java/res/drawable-xhdpi/fragment_adblock_custom_item_remove.png + create mode 100644 components/adblock/android/java/res/drawable-xxhdpi/fragment_adblock_custom_item_add.png + create mode 100644 components/adblock/android/java/res/drawable-xxhdpi/fragment_adblock_custom_item_remove.png + create mode 100644 components/adblock/android/java/res/layout/adblock_custom_item.xml + create mode 100644 components/adblock/android/java/res/layout/adblock_custom_item_settings.xml + create mode 100644 components/adblock/android/java/res/layout/adblock_filter_lists_list_item.xml + create mode 100644 components/adblock/android/java/res/values/adblock_settings_locales_titles.xml + create mode 100644 components/adblock/android/java/res/xml/adblock_more_options.xml + create mode 100644 components/adblock/android/java/res/xml/adblock_preferences.xml + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/AdblockComposeFilterSuggestionsCallback.java + 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/AdblockElement.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockAllowedDomainsFragment.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockCustomFilterListsFragment.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockCustomFiltersFragment.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockCustomItemFragment.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockFilterListsAdapter.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockFilterListsFragment.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockMoreOptionsFragment.java + create mode 100644 components/adblock/android/java/src/org/chromium/components/adblock/settings/AdblockSettingsFragment.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockControllerTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockFilterFragmentTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupInfoBarTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/AdblockPopupMessageTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCircumventionTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesCspTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuInvTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideEmuTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesElemhideTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesExceptionTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesFilterTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesHeaderFilterTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesRewriteTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSiteKeyTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesSnippetsTest.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesTestsHelper.java + create mode 100644 components/adblock/android/javatests/src/org/chromium/components/adblock/TestPagesWebsocketTest.java + create mode 100644 components/adblock/android/translations/adblock_strings_af.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_am.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ar.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_as.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_az.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_be.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_bg.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_bn.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_bs.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ca.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_cs.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_da.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_de.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_el.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_en-GB.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_es-419.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_es.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_et.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_eu.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_fa.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_fi.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_fil.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_fr-CA.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_fr.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_gl.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_gu.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_hi.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_hr.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_hu.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_hy.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_id.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_is.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_it.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_iw.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ja.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ka.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_kk.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_km.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_kn.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ko.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ky.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_lo.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_lt.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_lv.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_mk.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ml.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_mn.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_mr.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ms.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_my.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ne.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_nl.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_no.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_or.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_pa.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_pl.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_pt-BR.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_pt-PT.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ro.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ru.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_si.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_sk.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_sl.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_sq.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_sr-Latn.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_sr.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_sv.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_sw.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ta.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_te.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_th.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_tr.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_uk.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_ur.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_uz.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_vi.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_zh-CN.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_zh-HK.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_zh-TW.xtb + create mode 100644 components/adblock/android/translations/adblock_strings_zu.xtb + create mode 100644 components/adblock/content/BUILD.gn + create mode 100644 components/adblock/content/browser/BUILD.gn + create mode 100644 components/adblock/content/browser/adblock_content_utils.cc + create mode 100644 components/adblock/content/browser/adblock_content_utils.h + create mode 100644 components/adblock/content/browser/adblock_webcontents_observer.cc + create mode 100644 components/adblock/content/browser/adblock_webcontents_observer.h + create mode 100644 components/adblock/content/browser/content_security_policy_injector.h + create mode 100644 components/adblock/content/browser/content_security_policy_injector_impl.cc + create mode 100644 components/adblock/content/browser/content_security_policy_injector_impl.h + create mode 100644 components/adblock/content/browser/element_hider.h + create mode 100644 components/adblock/content/browser/element_hider_impl.cc + create mode 100644 components/adblock/content/browser/element_hider_impl.h + create mode 100644 components/adblock/content/browser/frame_hierarchy_builder.cc + create mode 100644 components/adblock/content/browser/frame_hierarchy_builder.h + create mode 100644 components/adblock/content/browser/resource_classification_runner.h + create mode 100644 components/adblock/content/browser/resource_classification_runner_impl.cc + create mode 100644 components/adblock/content/browser/resource_classification_runner_impl.h + create mode 100644 components/adblock/content/browser/session_stats_impl.cc + create mode 100644 components/adblock/content/browser/session_stats_impl.h + create mode 100644 components/adblock/content/browser/test/adblock_content_utils_test.cc + create mode 100644 components/adblock/content/browser/test/adblock_webcontents_observer_test.cc + create mode 100644 components/adblock/content/browser/test/content_security_policy_injector_impl_test.cc + create mode 100644 components/adblock/content/browser/test/element_hider_impl_test.cc + create mode 100644 components/adblock/content/browser/test/frame_hierarchy_builder_test.cc + create mode 100644 components/adblock/content/browser/test/mock_adblock_content_security_policy_injector.cc + create mode 100644 components/adblock/content/browser/test/mock_adblock_content_security_policy_injector.h + create mode 100644 components/adblock/content/browser/test/mock_element_hider.cc + create mode 100644 components/adblock/content/browser/test/mock_element_hider.h + create mode 100644 components/adblock/content/browser/test/mock_frame_hierarchy_builder.cc + create mode 100644 components/adblock/content/browser/test/mock_frame_hierarchy_builder.h + create mode 100644 components/adblock/content/browser/test/mock_resource_classification_runner.cc + create mode 100644 components/adblock/content/browser/test/mock_resource_classification_runner.h + create mode 100644 components/adblock/content/browser/test/resource_classification_runner_impl_test.cc + create mode 100644 components/adblock/content/browser/test/session_stats_impl_test.cc + create mode 100644 components/adblock/content/common/BUILD.gn + create mode 100644 components/adblock/content/common/adblock_url_loader_factory.cc + create mode 100644 components/adblock/content/common/adblock_url_loader_factory.h + create mode 100644 components/adblock/content/common/adblock_url_loader_factory_for_test.cc + create mode 100644 components/adblock/content/common/adblock_url_loader_factory_for_test.h + create mode 100644 components/adblock/content/common/mojom/BUILD.gn + create mode 100644 components/adblock/content/common/mojom/adblock.mojom + create mode 100644 components/adblock/content/common/test/mock_adblock_mojo_interface.cc + create mode 100644 components/adblock/content/common/test/mock_adblock_mojo_interface.h + create mode 100644 components/adblock/core/BUILD.gn + create mode 100644 components/adblock/core/activeping_telemetry_topic_provider.cc + create mode 100644 components/adblock/core/activeping_telemetry_topic_provider.h + create mode 100644 components/adblock/core/adblock_controller.h + create mode 100644 components/adblock/core/adblock_controller_impl.cc + create mode 100644 components/adblock/core/adblock_controller_impl.h + create mode 100644 components/adblock/core/adblock_switches.cc + create mode 100644 components/adblock/core/adblock_switches.h + create mode 100644 components/adblock/core/adblock_telemetry_service.cc + create mode 100644 components/adblock/core/adblock_telemetry_service.h + create mode 100644 components/adblock/core/classifier/BUILD.gn + create mode 100644 components/adblock/core/classifier/resource_classifier.cc + create mode 100644 components/adblock/core/classifier/resource_classifier.h + create mode 100644 components/adblock/core/classifier/resource_classifier_impl.cc + create mode 100644 components/adblock/core/classifier/resource_classifier_impl.h + create mode 100644 components/adblock/core/classifier/test/mock_resource_classifier.cc + create mode 100644 components/adblock/core/classifier/test/mock_resource_classifier.h + create mode 100644 components/adblock/core/classifier/test/resource_classifier_impl_test.cc + create mode 100644 components/adblock/core/classifier/test/resource_classifier_perftest.cc + create mode 100644 components/adblock/core/common/BUILD.gn + create mode 100644 components/adblock/core/common/adblock_constants.cc + create mode 100644 components/adblock/core/common/adblock_constants.h + create mode 100644 components/adblock/core/common/adblock_prefs.cc + create mode 100644 components/adblock/core/common/adblock_prefs.h + create mode 100644 components/adblock/core/common/adblock_utils.cc + create mode 100644 components/adblock/core/common/adblock_utils.h + create mode 100644 components/adblock/core/common/allowed_connection_type.cc + create mode 100644 components/adblock/core/common/allowed_connection_type.h + create mode 100644 components/adblock/core/common/content_type.cc + create mode 100644 components/adblock/core/common/content_type.h + create mode 100644 components/adblock/core/common/converter_result.cc + create mode 100644 components/adblock/core/common/converter_result.h + create mode 100644 components/adblock/core/common/flatbuffer_data.cc + create mode 100644 components/adblock/core/common/flatbuffer_data.h + create mode 100644 components/adblock/core/common/header_filter_data.h + create mode 100644 components/adblock/core/common/keyword_extractor_utils.cc + create mode 100644 components/adblock/core/common/keyword_extractor_utils.h + create mode 100644 components/adblock/core/common/sitekey.h + create mode 100644 components/adblock/core/common/test/adblock_utils_test.cc + create mode 100644 components/adblock/core/common/test/flatbuffer_data_test.cc + create mode 100644 components/adblock/core/converter/BUILD.gn + create mode 100644 components/adblock/core/converter/converter.cc + create mode 100644 components/adblock/core/converter/converter.h + create mode 100644 components/adblock/core/converter/converter_standalone.cc + create mode 100644 components/adblock/core/converter/filter_keyword_extractor.cc + create mode 100644 components/adblock/core/converter/filter_keyword_extractor.h + create mode 100644 components/adblock/core/converter/metadata.cc + create mode 100644 components/adblock/core/converter/metadata.h + create mode 100644 components/adblock/core/converter/snippet_tokenizer.h + create mode 100644 components/adblock/core/converter/snippet_tokenizer_impl.cc + create mode 100644 components/adblock/core/converter/snippet_tokenizer_impl.h + create mode 100644 components/adblock/core/converter/test/converter_perftest.cc + create mode 100644 components/adblock/core/converter/test/converter_test.cc + create mode 100644 components/adblock/core/converter/test/filter_keyword_extractor_test.cc + create mode 100644 components/adblock/core/converter/test/metadata_test.cc + create mode 100644 components/adblock/core/converter/test/mock_snippet_tokenizer.cc + create mode 100644 components/adblock/core/converter/test/mock_snippet_tokenizer.h + create mode 100644 components/adblock/core/converter/test/snippet_tokenizer_impl_test.cc + create mode 100644 components/adblock/core/features.cc + create mode 100644 components/adblock/core/features.gni + create mode 100644 components/adblock/core/features.h + create mode 100644 components/adblock/core/schema/filter_list_schema.fbs + create mode 100644 components/adblock/core/session_stats.h + create mode 100644 components/adblock/core/sitekey_storage.h + create mode 100644 components/adblock/core/sitekey_storage_impl.cc + create mode 100644 components/adblock/core/sitekey_storage_impl.h + create mode 100644 components/adblock/core/subscription/BUILD.gn + create mode 100644 components/adblock/core/subscription/domain_splitter.cc + create mode 100644 components/adblock/core/subscription/domain_splitter.h + create mode 100644 components/adblock/core/subscription/installed_subscription.cc + create mode 100644 components/adblock/core/subscription/installed_subscription.h + create mode 100644 components/adblock/core/subscription/installed_subscription_impl.cc + create mode 100644 components/adblock/core/subscription/installed_subscription_impl.h + create mode 100644 components/adblock/core/subscription/ongoing_subscription_request.h + create mode 100644 components/adblock/core/subscription/ongoing_subscription_request_impl.cc + create mode 100644 components/adblock/core/subscription/ongoing_subscription_request_impl.h + create mode 100644 components/adblock/core/subscription/preloaded_subscription_provider.h + create mode 100644 components/adblock/core/subscription/preloaded_subscription_provider_impl.cc + create mode 100644 components/adblock/core/subscription/preloaded_subscription_provider_impl.h + create mode 100644 components/adblock/core/subscription/subscription.cc + create mode 100644 components/adblock/core/subscription/subscription.h + create mode 100644 components/adblock/core/subscription/subscription_collection.h + create mode 100644 components/adblock/core/subscription/subscription_collection_impl.cc + create mode 100644 components/adblock/core/subscription/subscription_collection_impl.h + create mode 100644 components/adblock/core/subscription/subscription_config.cc + create mode 100644 components/adblock/core/subscription/subscription_config.h + create mode 100644 components/adblock/core/subscription/subscription_downloader.h + create mode 100644 components/adblock/core/subscription/subscription_downloader_impl.cc + create mode 100644 components/adblock/core/subscription/subscription_downloader_impl.h + create mode 100644 components/adblock/core/subscription/subscription_persistent_metadata.h + create mode 100644 components/adblock/core/subscription/subscription_persistent_metadata_impl.cc + create mode 100644 components/adblock/core/subscription/subscription_persistent_metadata_impl.h + create mode 100644 components/adblock/core/subscription/subscription_persistent_storage.h + create mode 100644 components/adblock/core/subscription/subscription_persistent_storage_impl.cc + create mode 100644 components/adblock/core/subscription/subscription_persistent_storage_impl.h + create mode 100644 components/adblock/core/subscription/subscription_service.h + create mode 100644 components/adblock/core/subscription/subscription_service_impl.cc + create mode 100644 components/adblock/core/subscription/subscription_service_impl.h + create mode 100644 components/adblock/core/subscription/subscription_updater.h + create mode 100644 components/adblock/core/subscription/subscription_updater_impl.cc + create mode 100644 components/adblock/core/subscription/subscription_updater_impl.h + create mode 100644 components/adblock/core/subscription/subscription_validator.cc + create mode 100644 components/adblock/core/subscription/subscription_validator.h + create mode 100644 components/adblock/core/subscription/subscription_validator_impl.cc + create mode 100644 components/adblock/core/subscription/subscription_validator_impl.h + create mode 100644 components/adblock/core/subscription/test/installed_subscription_impl_test.cc + create mode 100644 components/adblock/core/subscription/test/mock_installed_subscription.cc + create mode 100644 components/adblock/core/subscription/test/mock_installed_subscription.h + create mode 100644 components/adblock/core/subscription/test/mock_subscription.cc + create mode 100644 components/adblock/core/subscription/test/mock_subscription.h + create mode 100644 components/adblock/core/subscription/test/mock_subscription_collection.cc + create mode 100644 components/adblock/core/subscription/test/mock_subscription_collection.h + create mode 100644 components/adblock/core/subscription/test/mock_subscription_downloader.cc + create mode 100644 components/adblock/core/subscription/test/mock_subscription_downloader.h + create mode 100644 components/adblock/core/subscription/test/mock_subscription_persistent_metadata.cc + create mode 100644 components/adblock/core/subscription/test/mock_subscription_persistent_metadata.h + create mode 100644 components/adblock/core/subscription/test/mock_subscription_service.cc + create mode 100644 components/adblock/core/subscription/test/mock_subscription_service.h + create mode 100644 components/adblock/core/subscription/test/mock_subscription_updater.cc + create mode 100644 components/adblock/core/subscription/test/mock_subscription_updater.h + create mode 100644 components/adblock/core/subscription/test/ongoing_subscription_request_impl_test.cc + create mode 100644 components/adblock/core/subscription/test/preloaded_subscription_provider_impl_test.cc + create mode 100644 components/adblock/core/subscription/test/subscription_collection_impl_test.cc + create mode 100644 components/adblock/core/subscription/test/subscription_downloader_impl_test.cc + create mode 100644 components/adblock/core/subscription/test/subscription_persistent_metadata_impl_test.cc + create mode 100644 components/adblock/core/subscription/test/subscription_persistent_storage_impl_test.cc + create mode 100644 components/adblock/core/subscription/test/subscription_service_impl_test.cc + create mode 100644 components/adblock/core/subscription/test/subscription_updater_impl_test.cc + create mode 100644 components/adblock/core/subscription/test/subscription_validator_impl_test.cc + create mode 100644 components/adblock/core/subscription/test/url_keyword_extractor_test.cc + create mode 100644 components/adblock/core/subscription/url_keyword_extractor.cc + create mode 100644 components/adblock/core/subscription/url_keyword_extractor.h + create mode 100644 components/adblock/core/test/activeping_telemetry_topic_provider_test.cc + create mode 100644 components/adblock/core/test/adblock_controller_impl_test.cc + create mode 100644 components/adblock/core/test/adblock_telemetry_service_unittest.cc + create mode 100644 components/adblock/core/test/bundled_subscription_test.cc + create mode 100644 components/adblock/core/test/mock_adblock_controller.cc + create mode 100644 components/adblock/core/test/mock_adblock_controller.h + create mode 100644 components/adblock/core/test/mock_sitekey_storage.cc + create mode 100644 components/adblock/core/test/mock_sitekey_storage.h + create mode 100644 components/adblock/core/test/sitekey_storage_impl_test.cc + create mode 100644 components/adblock/docs/ad-filtering/README.md + create mode 100644 components/adblock/docs/ad-filtering/element-hiding-sequence.png + create mode 100644 components/adblock/docs/ad-filtering/element-hiding-sequence.txt + create mode 100644 components/adblock/docs/ad-filtering/element-hiding.md + create mode 100644 components/adblock/docs/ad-filtering/filter-lists.md + create mode 100644 components/adblock/docs/ad-filtering/request-filter-matching-sequence.png + create mode 100644 components/adblock/docs/ad-filtering/request_filter_matching_sequence.txt + create mode 100644 components/adblock/docs/ad-filtering/resource-filtering.md + create mode 100644 components/adblock/docs/ad-filtering/response-filter-matching-sequence.png + create mode 100644 components/adblock/docs/ad-filtering/response_filter_matching_sequence.txt + create mode 100644 components/adblock/docs/ad-filtering/snippets.md + create mode 100644 components/adblock/docs/adr/README.md + create mode 100644 components/adblock/docs/adr/consuming-full-filter-lists.md + create mode 100644 components/adblock/docs/adr/moving-user-counting-to-dedicated-service.md + create mode 100644 components/adblock/docs/adr/not-extending-subresource-filter.md + create mode 100644 components/adblock/docs/adr/storing-filter-lists-in-flatbuffers-format.md + create mode 100644 components/adblock/docs/data-collection/README.md + create mode 100644 components/adblock/docs/data-collection/user-counting.md + create mode 100644 components/adblock/docs/design-overview.md + create mode 100644 components/adblock/docs/developer-notes.md + create mode 100644 components/adblock/docs/initialization-sequence.png + create mode 100644 components/adblock/docs/initialization-sequence.txt + create mode 100644 components/adblock/docs/integration-how-to.md + create mode 100644 components/adblock/docs/settings/README.md + create mode 100644 components/adblock/docs/settings/user-setting-sequence.png + create mode 100644 components/adblock/docs/settings/user-setting-sequence.txt + create mode 100644 components/adblock_comparison/BUILD.gn + create mode 100644 components/adblock_comparison/libadblockplus_reference_database.cc + create mode 100644 components/adblock_comparison/libadblockplus_reference_database.h + create mode 100644 components/adblock_comparison/test_request_reader.cc + create mode 100644 components/adblock_comparison/test_request_reader.h + create mode 100644 components/adblock_comparison/verify_flatbuffer_adblocking.cc + create mode 100644 components/resources/adblock_resources.grdp + create mode 100644 components/resources/adblocking/.gitignore + create mode 100644 components/resources/adblocking/BUILD.gn + create mode 100644 components/resources/adblocking/anticv.txt + create mode 100644 components/resources/adblocking/easylist.txt + create mode 100644 components/resources/adblocking/elemhide.js + create mode 100644 components/resources/adblocking/elemhide_for_selector.jst + create mode 100644 components/resources/adblocking/elemhideemu.jst + create mode 100644 components/resources/adblocking/exceptionrules.txt + create mode 100755 components/resources/adblocking/update.sh + create mode 100644 components/test/data/adblock/anticv.txt + create mode 100644 components/test/data/adblock/easylist.txt + create mode 100644 components/test/data/adblock/exceptionrules.txt + create mode 100644 components/test/data/adblock/longurl.txt + create mode 100644 components/test/data/adblock/random_shuf_100.tsv.sqlite + create mode 100644 gclient/.gclient + create mode 100644 gclient/.gclient_ci_android + create mode 100644 gclient/.gclient_ci_linux + create mode 100644 gclient/.gclient_ci_windows + create mode 100755 tools/adblock/interdiff.py + create mode 100644 tools/perf/benchmarks/eyeo.py + create mode 100644 tools/perf/page_sets/eyeo_page_set.py + +diff --git a/DEPS b/DEPS +--- a/DEPS ++++ b/DEPS +@@ -169,6 +169,10 @@ vars = { + # flag is set True. + 'checkout_wpr_archives': False, + ++ # Eyeo WPR archives are kept separately from Chromium WPRs due to ++ # access restrictions (authenticated Google Cloud Storage). ++ 'checkout_eyeo_wpr_archives': False, ++ + # By default, do not check out WebKit for iOS, as it is not needed unless + # running against ToT WebKit rather than system WebKit. This can be overridden + # e.g. with custom_vars. +@@ -285,6 +289,8 @@ vars = { + 'use_rust': False, + + 'android_git': 'https://android.googlesource.com', ++ 'eyeo_distpartners_gitlab': 'https://gitlab.com/eyeo/distpartners', ++ 'eyeo_snippets_gitlab': 'https://gitlab.com/eyeo/snippets.git', + 'aomedia_git': 'https://aomedia.googlesource.com', + 'boringssl_git': 'https://boringssl.googlesource.com', + 'chromium_git': 'https://chromium.googlesource.com', +@@ -478,6 +484,11 @@ vars = { + # and whatever else without interference from each other. + 'ffmpeg_revision': '42601c274d7a39f5ded391024c52ff444f144f75', + ++ # Three lines of non-changing comments so that ++ # the commit queue can handle CLs rolling feed ++ # and whatever else without interference from each other. ++ 'eyeo_snippets_revision': 'v0.5.5', ++ + # If you change this, also update the libc++ revision in + # //buildtools/deps_revisions.gni. + 'libcxx_revision': 'db722166934ebc79a6e65e5fef9a6eae21eacb77', +@@ -772,6 +783,10 @@ deps = { + 'src/chrome/test/data/xr/webvr_info': + Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248', + ++ 'src/components/resources/adblocking/snippets': { ++ 'url': Var('eyeo_snippets_gitlab') + '@' + Var('eyeo_snippets_revision'), ++ }, ++ + 'src/docs/website': { + 'url': Var('chromium_git') + '/website.git' + '@' + '1b05569731b9b2d4f945fa3c87f3fa8a15a732e6', + }, +@@ -916,6 +931,15 @@ deps = { + 'dep_type': 'cipd', + }, + ++ 'src/tools/perf/eyeo_data': { ++ # We currently only have WPR recorded for Android. If we add Desktop ++ # recordings, remove `checkout_android` condition. ++ 'condition': ++ 'checkout_android and checkout_eyeo_wpr_archives', ++ 'url': ++ Var('eyeo_distpartners_gitlab') + '/web-page-recordings.git@ec931d65bce04c273d4a4cb4950d2a7f7aa2f37f', ++ }, ++ + 'src/third_party/accessibility_test_framework': { + 'packages': [ + { +diff --git a/README.md b/README.md +--- a/README.md ++++ b/README.md +@@ -19,3 +19,15 @@ Android WebView, Ash). Even if these products have multiple executables, the + code should be in subdirectories of the product. + + If you found a bug, please file it at https://crbug.com/new. ++ ++ ++## Eyeo Chromium SDK ++ ++Eyeo Chromium SDK is a fork of the Chromium project that ++integrates ad-filtering capabilities. A big part of the functionality is ++implemented inside a component, to simplify the integration with other ++modifications to the browser. ++ ++The [component folder](components/adblock) contains most of the source code, ++as well as the changelog, license and technical documentation about ++architecture and integration steps. +diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h +--- a/base/trace_event/builtin_categories.h ++++ b/base/trace_event/builtin_categories.h +@@ -1,6 +1,10 @@ + // Copyright 2018 The Chromium Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. ++// ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. + + #ifndef BASE_TRACE_EVENT_BUILTIN_CATEGORIES_H_ + #define BASE_TRACE_EVENT_BUILTIN_CATEGORIES_H_ +@@ -85,6 +89,7 @@ + X("exo") \ + X("extensions") \ + X("explore_sites") \ ++ X("eyeo") \ + X("FileSystem") \ + X("file_system_provider") \ + X("fledge") \ +diff --git a/build/install-build-deps.sh b/build/install-build-deps.sh +--- a/build/install-build-deps.sh ++++ b/build/install-build-deps.sh +@@ -4,6 +4,10 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++# This source code is a part of eyeo Chromium SDK. ++# Use of this source code is governed by the GPLv3 that can be found in the ++# components/adblock/LICENSE file. ++ + # Script to install everything needed to build chromium (well, ideally, anyway) + # See https://chromium.googlesource.com/chromium/src/+/main/docs/linux/build_instructions.md + +@@ -579,9 +583,11 @@ fi + if package_exists libinput-dev; then + dev_list="${dev_list} libinput-dev" + fi +-if package_exists snapcraft; then +- dev_list="${dev_list} snapcraft" +-fi ++#Do NOT install snapcraft, as it hangs inside Docker trying to connect to the ++#store and preventing automated package updates. ++#if package_exists snapcraft; then ++# dev_list="${dev_list} snapcraft" ++#fi + + # Cross-toolchain strip is needed for building the sysroots. + if package_exists binutils-arm-linux-gnueabihf; then +diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn +--- a/chrome/android/BUILD.gn ++++ b/chrome/android/BUILD.gn +@@ -1,6 +1,10 @@ + # Copyright 2014 The Chromium Authors. All rights reserved. + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. ++# ++# This source code is a part of eyeo Chromium SDK. ++# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file. ++ + + import("//build/android/resource_sizes.gni") + import("//build/config/android/config.gni") +@@ -245,6 +249,7 @@ android_resources("chrome_app_java_resources") { + "//chrome/browser/ui/android/toolbar:java_resources", + "//chrome/browser/ui/android/webid/internal:java_resources", + "//chrome/browser/ui/messages/android:java_resources", ++ "//components/adblock/android:java_resources", + "//components/autofill/android:autofill_java_resources", + "//components/autofill/android:autofill_payments_java_resources", + "//components/blocked_content/android:java_resources", +@@ -458,6 +463,7 @@ android_library("chrome_java") { + "//chrome/browser/webapps/android:java", + "//chrome/browser/webauthn/android:java", + "//chrome/browser/xsurface:java", ++ "//components/adblock/android:adblock_java", + "//components/autofill/android:autofill_java", + "//components/autofill/android:prefeditor_autofill_java", + "//components/autofill_assistant/android:public_dependencies_java", +@@ -863,6 +869,7 @@ group("jni_headers") { + "//chrome/browser/ui/messages/android:jni_headers", + "//chrome/browser/util:jni_headers", + "//chrome/browser/webauthn/android:jni_headers", ++ "//components/adblock/android:jni_headers", + "//components/autofill_assistant/android:jni_headers", + "//components/autofill_assistant/android:jni_headers_public", + "//components/autofill_assistant/android:jni_headers_public_dependencies", +@@ -1609,6 +1616,7 @@ android_library("chrome_test_java") { + "//chrome/test/android:chrome_java_integration_test_support", + "//chrome/test/android:chrome_java_test_pagecontroller", + "//chrome/test/android/test_trusted_web_activity:test_trusted_web_activity_java", ++ "//components/adblock/android:adblock_java_tests", + "//components/autofill/android:autofill_java", + "//components/autofill/android:prefeditor_autofill_java", + "//components/autofill_assistant/android:public_dependencies_java", +diff --git a/chrome/android/chrome_common_shared_library.gni b/chrome/android/chrome_common_shared_library.gni +--- a/chrome/android/chrome_common_shared_library.gni ++++ b/chrome/android/chrome_common_shared_library.gni +@@ -1,6 +1,10 @@ + # Copyright 2018 The Chromium Authors. All rights reserved. + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. ++# ++# This source code is a part of eyeo Chromium SDK. ++# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file. ++ + + import("//base/android/linker/config.gni") + import("//build/config/android/config.gni") +diff --git a/chrome/android/java/res/xml/main_preferences.xml b/chrome/android/java/res/xml/main_preferences.xml +--- a/chrome/android/java/res/xml/main_preferences.xml ++++ b/chrome/android/java/res/xml/main_preferences.xml +@@ -1,7 +1,11 @@ + + ++ found in the LICENSE file. ++ ++ This source code is a part of eyeo Chromium SDK. ++ Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file.--> ++ + + ++ + + + + + + + +diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc +--- a/chrome/app/chrome_main_delegate.cc ++++ b/chrome/app/chrome_main_delegate.cc +@@ -1,6 +1,10 @@ + // Copyright (c) 2012 The Chromium Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. ++// ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. + + #include "chrome/app/chrome_main_delegate.h" + +@@ -38,6 +42,7 @@ + #include "base/trace_event/trace_event_impl.h" + #include "build/build_config.h" + #include "build/chromeos_buildflags.h" ++#include "chrome/browser/adblock/adblock_content_browser_client.h" + #include "chrome/browser/chrome_content_browser_client.h" + #include "chrome/browser/chrome_resource_bundle_helper.h" + #include "chrome/browser/defaults.h" +@@ -1486,7 +1491,7 @@ content::ContentClient* ChromeMainDelegate::CreateContentClient() { + content::ContentBrowserClient* + ChromeMainDelegate::CreateContentBrowserClient() { + chrome_content_browser_client_ = +- std::make_unique(); ++ std::make_unique(); + return chrome_content_browser_client_.get(); + } + +diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn +--- a/chrome/browser/BUILD.gn ++++ b/chrome/browser/BUILD.gn +@@ -1,6 +1,9 @@ + # Copyright 2014 The Chromium Authors. All rights reserved. + # Use of this source code is governed by a BSD - style license that can be + # found in the LICENSE file. ++# ++# This source code is a part of eyeo Chromium SDK. ++# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file. + + import("//base/allocator/allocator.gni") + import("//build/buildflag_header.gni") +@@ -15,6 +18,7 @@ import("//chrome/browser/buildflags.gni") + import("//chrome/browser/downgrade/buildflags.gni") + import("//chrome/common/features.gni") + import("//chromeos/ash/components/assistant/assistant.gni") ++import("//components/adblock/core/features.gni") + import("//components/captive_portal/core/features.gni") + import("//components/exo/buildflags.gni") + import("//components/feed/features.gni") +@@ -149,6 +153,30 @@ static_library("browser") { + "accessibility/page_colors.h", + "accessibility/page_colors_factory.cc", + "accessibility/page_colors_factory.h", ++ "adblock/adblock_content_browser_client.cc", ++ "adblock/adblock_content_browser_client.h", ++ "adblock/adblock_controller_factory.cc", ++ "adblock/adblock_controller_factory.h", ++ "adblock/adblock_mojo_interface_impl.cc", ++ "adblock/adblock_mojo_interface_impl.h", ++ "adblock/adblock_telemetry_service_factory.cc", ++ "adblock/adblock_telemetry_service_factory.h", ++ "adblock/content_security_policy_injector_factory.cc", ++ "adblock/content_security_policy_injector_factory.h", ++ "adblock/element_hider_factory.cc", ++ "adblock/element_hider_factory.h", ++ "adblock/resource_classification_runner_factory.cc", ++ "adblock/resource_classification_runner_factory.h", ++ "adblock/session_stats_factory.cc", ++ "adblock/session_stats_factory.h", ++ "adblock/sitekey_storage_factory.cc", ++ "adblock/sitekey_storage_factory.h", ++ "adblock/subscription_persistent_metadata_factory.cc", ++ "adblock/subscription_persistent_metadata_factory.h", ++ "adblock/subscription_service_factory.cc", ++ "adblock/subscription_service_factory.h", ++ "adblock/subscription_updater_factory.cc", ++ "adblock/subscription_updater_factory.h", + "after_startup_task_utils.cc", + "after_startup_task_utils.h", + "app_mode/app_mode_utils.cc", +@@ -2018,6 +2046,8 @@ static_library("browser") { + "//chrome/common/notifications", + "//chrome/installer/util:with_no_strings", + "//chrome/services/speech/buildflags", ++ "//components/adblock/content:browser", ++ "//components/adblock/content:common", + "//components/assist_ranker", + "//components/autofill/content/browser", + "//components/autofill/core/browser", +@@ -2498,6 +2528,10 @@ static_library("browser") { + if (is_android) { + sources += [ + "after_startup_task_utils_android.cc", ++ "android/adblock/adblock_jni.cc", ++ "android/adblock/adblock_jni.h", ++ "android/adblock/adblock_jni_factory.cc", ++ "android/adblock/adblock_jni_factory.h", + "android/android_theme_resources.h", + "android/autocomplete/tab_matcher_android.cc", + "android/autocomplete/tab_matcher_android.h", +@@ -3251,6 +3285,7 @@ static_library("browser") { + "webauthn/android/conditional_ui_delegate_android.cc", + "webauthn/android/conditional_ui_delegate_android.h", + ] ++ + public_deps += [ + "//chrome/android/features/dev_ui:buildflags", + "//components/image_fetcher/core", +diff --git a/chrome/browser/adblock/README.md b/chrome/browser/adblock/README.md +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/README.md +@@ -0,0 +1,3 @@ ++This folder contains the OS-agnostic, Chrome-specific source code of eyeo Chromium SDK. ++ ++For the full documentation, refer to [components/adblock](/components/adblock). +diff --git a/chrome/browser/adblock/adblock_content_browser_client.cc b/chrome/browser/adblock/adblock_content_browser_client.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_content_browser_client.cc +@@ -0,0 +1,309 @@ ++/* ++ * 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 . ++ */ ++ ++#include "chrome/browser/adblock/adblock_content_browser_client.h" ++ ++#include "base/containers/unique_ptr_adapters.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/adblock_mojo_interface_impl.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ui/browser_navigator_params.h" ++#include "components/adblock/content/browser/resource_classification_runner.h" ++#include "components/adblock/content/common/adblock_url_loader_factory.h" ++#ifndef NDEBUG ++#include "components/adblock/content/common/adblock_url_loader_factory_for_test.h" ++#endif ++#include "components/adblock/content/common/mojom/adblock.mojom.h" ++#include "components/adblock/core/common/adblock_prefs.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "components/embedder_support/user_agent_utils.h" ++#include "components/prefs/pref_service.h" ++#include "content/public/browser/browser_task_traits.h" ++#include "content/public/browser/browser_thread.h" ++#include "content/public/browser/render_frame_host.h" ++#include "content/public/browser/render_process_host.h" ++#include "content/public/browser/render_view_host.h" ++#include "content/public/browser/web_contents.h" ++#include "mojo/public/cpp/bindings/self_owned_receiver.h" ++#include "services/network/public/mojom/websocket.mojom.h" ++#include "services/service_manager/public/cpp/binder_registry.h" ++#include "third_party/blink/public/common/loader/url_loader_throttle.h" ++ ++namespace { ++ ++bool IsAdblockEnabled(content::RenderFrameHost* frame) { ++ if (frame) { ++ auto* profile = ++ Profile::FromBrowserContext(frame->GetProcess()->GetBrowserContext()); ++ if (profile) { ++ return profile->GetPrefs()->GetBoolean(adblock::prefs::kEnableAdblock); ++ } ++ } ++ return false; ++} ++ ++// Owns all of the AdblockURLLoaderFactory for a given Profile. ++class AdblockContextData : public base::SupportsUserData::Data { ++ public: ++ AdblockContextData(const AdblockContextData&) = delete; ++ AdblockContextData& operator=(const AdblockContextData&) = delete; ++ ~AdblockContextData() override = default; ++ ++ static void StartProxying( ++ Profile* profile, ++ content::RenderFrameHost* frame, ++ int render_process_id, ++ mojo::PendingReceiver receiver, ++ mojo::PendingRemote target_factory, ++ content::ContentBrowserClient::URLLoaderFactoryType type) { ++ const void* const kAdblockContextUserDataKey = &kAdblockContextUserDataKey; ++ auto* self = static_cast( ++ profile->GetUserData(kAdblockContextUserDataKey)); ++ if (!self) { ++ self = new AdblockContextData(); ++ profile->SetUserData(kAdblockContextUserDataKey, base::WrapUnique(self)); ++ } ++#ifndef NDEBUG ++ content::WebContents* wc = content::WebContents::FromRenderFrameHost(frame); ++ bool is_adblock_test_url = ++ (type == ++ content::ContentBrowserClient::URLLoaderFactoryType::kNavigation) && ++ wc->GetVisibleURL().is_valid() && ++ wc->GetVisibleURL().host() == ++ adblock::AdblockURLLoaderFactoryForTest::kAdblockDebugDataHostName; ++ if (is_adblock_test_url) { ++ auto proxy = std::make_unique( ++ std::make_unique( ++ render_process_id), ++ frame->GetRoutingID(), std::move(receiver), std::move(target_factory), ++ embedder_support::GetUserAgent(), ++ base::BindOnce(&AdblockContextData::RemoveProxy, ++ self->weak_factory_.GetWeakPtr()), ++ adblock::AdblockControllerFactory::GetForBrowserContext( ++ Profile::FromBrowserContext( ++ frame->GetProcess()->GetBrowserContext()))); ++ self->proxies_.emplace(std::move(proxy)); ++ return; ++ } ++#endif ++ auto proxy = std::make_unique( ++ std::make_unique(render_process_id), ++ frame->GetRoutingID(), std::move(receiver), std::move(target_factory), ++ embedder_support::GetUserAgent(), ++ base::BindOnce(&AdblockContextData::RemoveProxy, ++ self->weak_factory_.GetWeakPtr())); ++ self->proxies_.emplace(std::move(proxy)); ++ } ++ ++ private: ++ void RemoveProxy(adblock::AdblockURLLoaderFactory* proxy) { ++ auto it = proxies_.find(proxy); ++ DCHECK(it != proxies_.end()); ++ proxies_.erase(it); ++ } ++ ++ AdblockContextData() = default; ++ ++ std::set, ++ base::UniquePtrComparator> ++ proxies_; ++ ++ base::WeakPtrFactory weak_factory_{this}; ++}; ++ ++} // namespace ++ ++AdblockContentBrowserClient::AdblockContentBrowserClient() = default; ++ ++AdblockContentBrowserClient::~AdblockContentBrowserClient() = default; ++ ++bool AdblockContentBrowserClient::CanCreateWindow( ++ content::RenderFrameHost* opener, ++ const GURL& opener_url, ++ const GURL& opener_top_level_frame_url, ++ const url::Origin& source_origin, ++ content::mojom::WindowContainerType container_type, ++ const GURL& target_url, ++ const content::Referrer& referrer, ++ const std::string& frame_name, ++ WindowOpenDisposition disposition, ++ const blink::mojom::WindowFeatures& features, ++ bool user_gesture, ++ bool opener_suppressed, ++ bool* no_javascript_access) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ DCHECK(opener); ++ ++ if (IsAdblockEnabled(opener)) { ++ content::WebContents* web_contents = ++ content::WebContents::FromRenderFrameHost(opener); ++ auto* subscription_service = ++ adblock::SubscriptionServiceFactory::GetForBrowserContext( ++ web_contents->GetBrowserContext()); ++ if (subscription_service->IsInitialized()) { ++ GURL popup_url(target_url); ++ web_contents->GetPrimaryMainFrame()->GetProcess()->FilterURL(false, ++ &popup_url); ++ auto* classification_runner = ++ adblock::ResourceClassificationRunnerFactory::GetForBrowserContext( ++ web_contents->GetBrowserContext()); ++ const auto popup_blocking_decision = ++ classification_runner->ShouldBlockPopup( ++ subscription_service->GetCurrentSnapshot(), ++ opener_top_level_frame_url, popup_url, opener); ++ if (popup_blocking_decision == ++ adblock::mojom::FilterMatchResult::kAllowRule) ++ return true; ++ if (popup_blocking_decision == ++ adblock::mojom::FilterMatchResult::kBlockRule) ++ return false; ++ // Otherwise, if eyeo adblocking is disabled or there is no rule that ++ // explicitly allows or blocks a popup, fall back on Chromium's built-in ++ // popup blocker. ++ DCHECK(popup_blocking_decision == ++ adblock::mojom::FilterMatchResult::kDisabled || ++ popup_blocking_decision == ++ adblock::mojom::FilterMatchResult::kNoRule); ++ } ++ } ++ ++ return ChromeContentBrowserClient::CanCreateWindow( ++ opener, opener_url, opener_top_level_frame_url, source_origin, ++ container_type, target_url, referrer, frame_name, disposition, features, ++ user_gesture, opener_suppressed, no_javascript_access); ++} ++ ++bool AdblockContentBrowserClient::WillInterceptWebSocket( ++ content::RenderFrameHost* frame) { ++ if (IsAdblockEnabled(frame)) { ++ return true; ++ } ++ ++ return ChromeContentBrowserClient::WillInterceptWebSocket(frame); ++} ++ ++void AdblockContentBrowserClient::CreateWebSocket( ++ content::RenderFrameHost* frame, ++ WebSocketFactory factory, ++ const GURL& url, ++ const net::SiteForCookies& site_for_cookies, ++ const absl::optional& user_agent, ++ mojo::PendingRemote ++ handshake_client) { ++ auto* profile = ++ Profile::FromBrowserContext(frame->GetProcess()->GetBrowserContext()); ++ if (profile && ++ profile->GetPrefs()->GetBoolean(adblock::prefs::kEnableAdblock)) { ++ auto* subscription_service = ++ adblock::SubscriptionServiceFactory::GetForBrowserContext(profile); ++ if (!subscription_service->IsInitialized()) { ++ subscription_service->RunWhenInitialized(base::BindOnce( ++ &AdblockContentBrowserClient::CreateWebSocket, ++ weak_factory_.GetWeakPtr(), frame, std::move(factory), url, ++ site_for_cookies, user_agent, std::move(handshake_client))); ++ return; ++ } ++ auto* classification_runner = ++ adblock::ResourceClassificationRunnerFactory::GetForBrowserContext( ++ profile); ++ classification_runner->CheckRequestFilterMatchForWebSocket( ++ subscription_service->GetCurrentSnapshot(), url, frame, ++ base::BindOnce( ++ &AdblockContentBrowserClient::OnWebSocketFilterCheckCompleted, ++ weak_factory_.GetWeakPtr(), frame, std::move(factory), url, ++ site_for_cookies, user_agent, std::move(handshake_client))); ++ } else { ++ DCHECK(ChromeContentBrowserClient::WillInterceptWebSocket(frame)); ++ ChromeContentBrowserClient::CreateWebSocket(frame, std::move(factory), url, ++ site_for_cookies, user_agent, ++ std::move(handshake_client)); ++ } ++} ++ ++void AdblockContentBrowserClient::OnWebSocketFilterCheckCompleted( ++ content::RenderFrameHost* frame, ++ ChromeContentBrowserClient::WebSocketFactory factory, ++ const GURL& url, ++ const net::SiteForCookies& site_for_cookies, ++ const absl::optional& user_agent, ++ mojo::PendingRemote ++ handshake_client, ++ adblock::mojom::FilterMatchResult result) { ++ const bool has_blocking_filter = ++ result == adblock::mojom::FilterMatchResult::kBlockRule; ++ if (!has_blocking_filter) { ++ LOG(INFO) << "[eyeo] Web socket allowed for " << url; ++ if (ChromeContentBrowserClient::WillInterceptWebSocket(frame)) { ++ ChromeContentBrowserClient::CreateWebSocket( ++ frame, std::move(factory), url, site_for_cookies, user_agent, ++ std::move(handshake_client)); ++ return; ++ } ++ ++ std::vector headers; ++ if (user_agent) { ++ headers.push_back(network::mojom::HttpHeader::New( ++ net::HttpRequestHeaders::kUserAgent, *user_agent)); ++ } ++ std::move(factory).Run(url, std::move(headers), std::move(handshake_client), ++ mojo::NullRemote(), mojo::NullRemote()); ++ } ++ ++ LOG(INFO) << "[eyeo] Web socket blocked for " << url; ++} ++ ++bool AdblockContentBrowserClient::WillCreateURLLoaderFactory( ++ content::BrowserContext* browser_context, ++ content::RenderFrameHost* frame, ++ int render_process_id, ++ URLLoaderFactoryType type, ++ const url::Origin& request_initiator, ++ absl::optional navigation_id, ++ ukm::SourceIdObj ukm_source_id, ++ mojo::PendingReceiver* factory_receiver, ++ mojo::PendingRemote* ++ header_client, ++ bool* bypass_redirect_checks, ++ bool* disable_secure_dns, ++ network::mojom::URLLoaderFactoryOverridePtr* factory_override) { ++ // Create Chromium proxy first as WebRequestProxyingURLLoaderFactory logic ++ // depends on being first proxy ++ bool use_chrome_proxy = ++ ChromeContentBrowserClient::WillCreateURLLoaderFactory( ++ browser_context, frame, render_process_id, type, request_initiator, ++ navigation_id, ukm_source_id, factory_receiver, header_client, ++ bypass_redirect_checks, disable_secure_dns, factory_override); ++ auto* profile = frame ? Profile::FromBrowserContext( ++ frame->GetProcess()->GetBrowserContext()) ++ : nullptr; ++ bool use_adblock_proxy = ++ (type == URLLoaderFactoryType::kDocumentSubResource || ++ type == URLLoaderFactoryType::kNavigation) && ++ profile && ++ profile->GetPrefs()->GetBoolean(adblock::prefs::kEnableAdblock); ++ if (use_adblock_proxy) { ++ auto proxied_receiver = std::move(*factory_receiver); ++ mojo::PendingRemote target_factory_remote; ++ *factory_receiver = target_factory_remote.InitWithNewPipeAndPassReceiver(); ++ AdblockContextData::StartProxying(profile, frame, render_process_id, ++ std::move(proxied_receiver), ++ std::move(target_factory_remote), type); ++ } ++ return use_adblock_proxy || use_chrome_proxy; ++} +diff --git a/chrome/browser/adblock/adblock_content_browser_client.h b/chrome/browser/adblock/adblock_content_browser_client.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_content_browser_client.h +@@ -0,0 +1,90 @@ ++/* ++ * 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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTENT_BROWSER_CLIENT_H_ ++#define CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTENT_BROWSER_CLIENT_H_ ++ ++#include "chrome/browser/chrome_content_browser_client.h" ++ ++namespace adblock::mojom { ++enum class FilterMatchResult; ++} // namespace adblock::mojom ++ ++/** ++ * @brief Intercepts network and UI events to inject ad-filtering. ++ * Provides ad-filtering implementations of URLLoaderThrottles. ++ * Binds a mojo connection between Renderer processes and the ++ * Browser-process-based ResourceClassificationRunner. ++ * Lives in browser process UI thread. ++ */ ++class AdblockContentBrowserClient : public ChromeContentBrowserClient { ++ public: ++ AdblockContentBrowserClient(); ++ ~AdblockContentBrowserClient() override; ++ ++ bool CanCreateWindow(content::RenderFrameHost* opener, ++ const GURL& opener_url, ++ const GURL& opener_top_level_frame_url, ++ const url::Origin& source_origin, ++ content::mojom::WindowContainerType container_type, ++ const GURL& target_url, ++ const content::Referrer& referrer, ++ const std::string& frame_name, ++ WindowOpenDisposition disposition, ++ const blink::mojom::WindowFeatures& features, ++ bool user_gesture, ++ bool opener_suppressed, ++ bool* no_javascript_access) override; ++ bool WillInterceptWebSocket(content::RenderFrameHost* frame) override; ++ void CreateWebSocket( ++ content::RenderFrameHost* frame, ++ WebSocketFactory factory, ++ const GURL& url, ++ const net::SiteForCookies& site_for_cookies, ++ const absl::optional& user_agent, ++ mojo::PendingRemote ++ handshake_client) override; ++ bool WillCreateURLLoaderFactory( ++ content::BrowserContext* browser_context, ++ content::RenderFrameHost* frame, ++ int render_process_id, ++ URLLoaderFactoryType type, ++ const url::Origin& request_initiator, ++ absl::optional navigation_id, ++ ukm::SourceIdObj ukm_source_id, ++ mojo::PendingReceiver* factory_receiver, ++ mojo::PendingRemote* ++ header_client, ++ bool* bypass_redirect_checks, ++ bool* disable_secure_dns, ++ network::mojom::URLLoaderFactoryOverridePtr* factory_override) override; ++ ++ private: ++ void OnWebSocketFilterCheckCompleted( ++ content::RenderFrameHost* frame, ++ ChromeContentBrowserClient::WebSocketFactory factory, ++ const GURL& url, ++ const net::SiteForCookies& site_for_cookies, ++ const absl::optional& user_agent, ++ mojo::PendingRemote ++ handshake_client, ++ adblock::mojom::FilterMatchResult result); ++ ++ base::WeakPtrFactory weak_factory_{this}; ++}; ++ ++#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTENT_BROWSER_CLIENT_H_ +diff --git a/chrome/browser/adblock/adblock_controller_factory.cc b/chrome/browser/adblock/adblock_controller_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_controller_factory.cc +@@ -0,0 +1,75 @@ ++/* ++ * 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 . ++ */ ++ ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/browser_process.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/core/adblock_controller_impl.h" ++#include "components/adblock/core/common/adblock_prefs.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "components/pref_registry/pref_registry_syncable.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++AdblockController* AdblockControllerFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++AdblockControllerFactory* AdblockControllerFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++AdblockControllerFactory::AdblockControllerFactory() ++ : BrowserContextKeyedServiceFactory( ++ "AdblockController", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(SubscriptionServiceFactory::GetInstance()); ++} ++ ++AdblockControllerFactory::~AdblockControllerFactory() = default; ++ ++KeyedService* AdblockControllerFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ auto controller = std::make_unique( ++ Profile::FromBrowserContext(context)->GetPrefs(), ++ SubscriptionServiceFactory::GetForBrowserContext(context), ++ g_browser_process->GetApplicationLocale()); ++ controller->SynchronizeWithPrefsWhenPossible(); ++ return controller.release(); ++} ++ ++content::BrowserContext* AdblockControllerFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++void AdblockControllerFactory::RegisterProfilePrefs( ++ user_prefs::PrefRegistrySyncable* registry) { ++ adblock::prefs::RegisterProfilePrefs(registry); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/adblock_controller_factory.h b/chrome/browser/adblock/adblock_controller_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_controller_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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTROLLER_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTROLLER_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 AdblockController; ++class AdblockControllerFactory : public BrowserContextKeyedServiceFactory { ++ public: ++ static AdblockController* GetForBrowserContext( ++ content::BrowserContext* context); ++ static AdblockControllerFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ AdblockControllerFactory(); ++ ~AdblockControllerFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++ void RegisterProfilePrefs( ++ user_prefs::PrefRegistrySyncable* registry) override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_CONTROLLER_FACTORY_H_ +diff --git a/chrome/browser/adblock/adblock_debug_url_browsertest.cc b/chrome/browser/adblock/adblock_debug_url_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_debug_url_browsertest.cc +@@ -0,0 +1,116 @@ ++// 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 . ++ ++#include ++ ++#include "chrome/browser/ui/browser.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/content/common/adblock_url_loader_factory_for_test.h" ++#include "content/public/test/browser_test.h" ++#include "testing/gmock/include/gmock/gmock.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++using testing::_; ++using testing::Mock; ++using testing::Return; ++ ++namespace { ++ ++class AdblockDebugUrlTest : public InProcessBrowserTest { ++ public: ++ AdblockDebugUrlTest() {} ++ ~AdblockDebugUrlTest() override = default; ++ AdblockDebugUrlTest(const AdblockDebugUrlTest&) = delete; ++ AdblockDebugUrlTest& operator=(const AdblockDebugUrlTest&) = delete; ++ ++ protected: ++ std::string ExecuteScriptAndExtractString(const std::string& js_code) const { ++ content::WebContents* web_contents = ++ browser()->tab_strip_model()->GetActiveWebContents(); ++ return content::EvalJs(web_contents->GetPrimaryMainFrame(), js_code) ++ .ExtractString(); ++ } ++ ++ static constexpr char kReadPageBodyScript[] = R"( ++ document.getElementsByTagName('body')[0].firstChild.innerHTML ++ )"; ++ ++ const std::string kAdblockDebugUrl = ++ "http://" + ++ adblock::AdblockURLLoaderFactoryForTest::kAdblockDebugDataHostName; ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestInvalidUrls) { ++ GURL invalid_command_url(kAdblockDebugUrl + "/some_invalid_command"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), invalid_command_url)); ++ ASSERT_EQ("INVALID_COMMAND", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL invalid_payload_url1(kAdblockDebugUrl + "/add?wrong_param=value"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), invalid_payload_url1)); ++ ASSERT_EQ("INVALID_PAYLOAD", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL invalid_payload_url2(kAdblockDebugUrl + "/add?wrongpayload=value"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), invalid_payload_url2)); ++ ASSERT_EQ("INVALID_PAYLOAD", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL invalid_payload_url3(kAdblockDebugUrl + "/add?payload="); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), invalid_payload_url3)); ++ ASSERT_EQ("INVALID_PAYLOAD", ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockDebugUrlTest, TestValidUrls) { ++ GURL clear_filters_url(kAdblockDebugUrl + "/clear"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_filters_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL list_filters_url(kAdblockDebugUrl + "/list"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ std::string expected_no_filters = "OK"; ++ ASSERT_EQ(expected_no_filters, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL add_filters_url(kAdblockDebugUrl + ++ "/add?payload=%2FadsPlugin%2F%2A%0A%2Fadsponsor."); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), add_filters_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ std::string expected_two_filters = "OK\n\n/adsPlugin/*\n/adsponsor.\n"; ++ ASSERT_EQ(expected_two_filters, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ GURL remove_filter_url(kAdblockDebugUrl + "/remove?payload=%2Fadsponsor."); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), remove_filter_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ std::string expected_one_filter = "OK\n\n/adsPlugin/*\n"; ++ ASSERT_EQ(expected_one_filter, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), clear_filters_url)); ++ ASSERT_EQ("OK", ExecuteScriptAndExtractString(kReadPageBodyScript)); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), list_filters_url)); ++ ASSERT_EQ(expected_no_filters, ++ ExecuteScriptAndExtractString(kReadPageBodyScript)); ++} ++ ++} // namespace +diff --git a/chrome/browser/adblock/adblock_frame_hierarchy_builder_browsertest.cc b/chrome/browser/adblock/adblock_frame_hierarchy_builder_browsertest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_frame_hierarchy_builder_browsertest.cc +@@ -0,0 +1,119 @@ ++/* ++ * 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 . ++ */ ++ ++#include "components/adblock/content/browser/frame_hierarchy_builder.h" ++ ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/browser/ui/browser.h" ++#include "chrome/test/base/in_process_browser_test.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "content/public/test/browser_test.h" ++#include "content/public/test/browser_test_utils.h" ++#include "net/dns/mock_host_resolver.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++namespace adblock { ++ ++// Simulated setup: ++// http://outer.com/outermost_frame.html ++// has an iframe: http://middle.com/middle_frame.html ++// has an iframe: http://inner.com/innermost_frame.html ++// has a subresource http://inner.com/resource.png ++// ++// All of these files are in chrome/test/data/adblock. Cross-domain distribution ++// is simulated via SetupCrossSiteRedirector. ++// innermost_frame.html reports whether resource.png is visible via ++// window.top.postMessage to outermost_frame.html, which stores a global ++// subresource_visible JS variable. ++class AdblockFrameHierarchyBrowserTest : public InProcessBrowserTest { ++ public: ++ void SetUpOnMainThread() override { ++ host_resolver()->AddRule("*", "127.0.0.1"); ++ embedded_test_server()->ServeFilesFromSourceDirectory( ++ "chrome/test/data/adblock"); ++ content::SetupCrossSiteRedirector(embedded_test_server()); ++ ASSERT_TRUE(embedded_test_server()->Start()); ++ } ++ ++ void SetFilters(std::vector filters) { ++ auto* subscription_service = ++ SubscriptionServiceFactory::GetForBrowserContext(browser()->profile()); ++ subscription_service->SetCustomFilters(std::move(filters)); ++ } ++ ++ void NavigateToOutermostFrame() { ++ ASSERT_TRUE(ui_test_utils::NavigateToURL( ++ browser(), embedded_test_server()->GetURL( ++ "/cross-site/outer.com/outermost_frame.html"))); ++ } ++ ++ void VerifyTargetResourceShown(bool expected_shown) { ++ EXPECT_EQ( ++ expected_shown, ++ content::EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), ++ "subresource_visible === true")); ++ } ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ SubresourceShownWithNoFilters) { ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(true); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, SubresourceBlocked) { ++ SetFilters({"/resource.png"}); ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(false); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ SubresourceAllowedViaInnerFrame) { ++ SetFilters({"/resource.png", "@@||inner.com^$document"}); ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(true); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ SubresourceAllowedViaMiddleFrame) { ++ SetFilters({"/resource.png", "@@||middle.com^$document"}); ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(true); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ SubresourceAllowedViaOutermostFrame) { ++ SetFilters({"/resource.png", "@@||outer.com^$document"}); ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(true); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockFrameHierarchyBrowserTest, ++ SubresourceBlockedWhenInvalidAllowRule) { ++ SetFilters({"/resource.png", "@@||bogus.com^$document"}); ++ NavigateToOutermostFrame(); ++ VerifyTargetResourceShown(false); ++} ++ ++// More tests can be added / parametrized, e.g.: ++// - elemhide blocking filters (in conjunction with $elemhide allow rules) ++// - $subdocument-based allow rules ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/adblock_mojo_interface_impl.cc b/chrome/browser/adblock/adblock_mojo_interface_impl.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_mojo_interface_impl.cc +@@ -0,0 +1,267 @@ ++/* ++ * 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 . ++ */ ++ ++#include "chrome/browser/adblock/adblock_mojo_interface_impl.h" ++#include ++ ++#include "chrome/browser/adblock/content_security_policy_injector_factory.h" ++#include "chrome/browser/adblock/element_hider_factory.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/adblock/sitekey_storage_factory.h" ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "components/adblock/content/browser/adblock_content_utils.h" ++#include "components/adblock/content/browser/content_security_policy_injector.h" ++#include "components/adblock/content/browser/element_hider.h" ++#include "components/adblock/content/browser/frame_hierarchy_builder.h" ++#include "components/adblock/content/browser/resource_classification_runner.h" ++#include "components/adblock/core/sitekey_storage.h" ++#include "components/adblock/core/subscription/subscription_service.h" ++#include "content/public/browser/browser_task_traits.h" ++#include "content/public/browser/render_frame_host.h" ++#include "content/public/browser/render_process_host.h" ++#include "services/network/public/mojom/parsed_headers.mojom.h" ++ ++namespace adblock { ++namespace { ++ ++SubscriptionService* GetSubscriptionService( ++ content::RenderProcessHost* process_host) { ++ auto* subscription_service = SubscriptionServiceFactory::GetForBrowserContext( ++ process_host->GetBrowserContext()); ++ DCHECK(subscription_service); ++ return subscription_service; ++} ++ ++// Without USER_BLOCKING priority - in session restore case - posted ++// callbacks can take over a minute to trigger. This is why such high ++// priority is applied everywhere. ++const base::TaskPriority kTaskResponsePriority = ++ base::TaskPriority::USER_BLOCKING; ++ ++} // namespace ++ ++// We cannot call mojo callback in stack, hence this UIThread posting ++void AdblockMojoInterfaceImpl::PostFilterMatchCallbackToUI( ++ mojom::AdblockInterface::CheckFilterMatchCallback callback, ++ mojom::FilterMatchResult result) { ++ content::GetUIThreadTaskRunner({kTaskResponsePriority}) ++ ->PostTask(FROM_HERE, base::BindOnce(std::move(callback), result)); ++} ++ ++// We cannot call mojo callback in stack, hence this UIThread posting ++void AdblockMojoInterfaceImpl::PostResponseHeadersCallbackToUI( ++ mojom::AdblockInterface::ProcessResponseHeadersCallback callback, ++ mojom::FilterMatchResult result, ++ network::mojom::ParsedHeadersPtr parsed_headers) { ++ content::GetUIThreadTaskRunner({kTaskResponsePriority}) ++ ->PostTask(FROM_HERE, base::BindOnce(std::move(callback), result, ++ std::move(parsed_headers))); ++} ++ ++// We cannot call mojo callback in stack, hence this UIThread posting ++void AdblockMojoInterfaceImpl::PostRewriteCallbackToUI( ++ base::OnceCallback&)> callback, ++ const absl::optional& url) { ++ content::GetUIThreadTaskRunner({kTaskResponsePriority}) ++ ->PostTask(FROM_HERE, base::BindOnce(std::move(callback), url)); ++} ++ ++AdblockMojoInterfaceImpl::AdblockMojoInterfaceImpl(int32_t render_process_id) ++ : render_process_id_(render_process_id) {} ++ ++AdblockMojoInterfaceImpl::~AdblockMojoInterfaceImpl() = default; ++ ++void AdblockMojoInterfaceImpl::CheckFilterMatch( ++ const GURL& request_url, ++ int32_t resource_type, ++ int32_t render_frame_id, ++ mojom::AdblockInterface::CheckFilterMatchCallback callback) { ++ auto* process_host = content::RenderProcessHost::FromID(render_process_id_); ++ if (!process_host) { ++ PostFilterMatchCallbackToUI(std::move(callback), ++ mojom::FilterMatchResult::kNoRule); ++ return; ++ } ++ ++ auto* subscription_service = GetSubscriptionService(process_host); ++ if (!subscription_service->IsInitialized()) { ++ subscription_service->RunWhenInitialized( ++ base::BindOnce(&AdblockMojoInterfaceImpl::CheckFilterMatch, ++ weak_ptr_factory_.GetWeakPtr(), request_url, ++ resource_type, render_frame_id, std::move(callback))); ++ return; ++ } ++ ++ auto* classification_runner = ++ ResourceClassificationRunnerFactory::GetForBrowserContext( ++ process_host->GetBrowserContext()); ++ DCHECK(classification_runner); ++ ++ classification_runner->CheckRequestFilterMatch( ++ subscription_service->GetCurrentSnapshot(), request_url, resource_type, ++ render_process_id_, render_frame_id, ++ base::BindOnce( ++ &AdblockMojoInterfaceImpl::OnRequestUrlClassified, ++ weak_ptr_factory_.GetWeakPtr(), request_url, render_frame_id, ++ resource_type, ++ base::BindOnce(&AdblockMojoInterfaceImpl::PostFilterMatchCallbackToUI, ++ weak_ptr_factory_.GetWeakPtr(), std::move(callback)))); ++} ++ ++void AdblockMojoInterfaceImpl::ProcessResponseHeaders( ++ const GURL& response_url, ++ int32_t render_frame_id, ++ const scoped_refptr& headers, ++ const std::string& user_agent, ++ mojom::AdblockInterface::ProcessResponseHeadersCallback callback) { ++ auto* process_host = content::RenderProcessHost::FromID(render_process_id_); ++ if (!process_host) { ++ PostResponseHeadersCallbackToUI(std::move(callback), ++ mojom::FilterMatchResult::kNoRule, nullptr); ++ return; ++ } ++ ++ auto* subscription_service = GetSubscriptionService(process_host); ++ if (!subscription_service->IsInitialized()) { ++ subscription_service->RunWhenInitialized(base::BindOnce( ++ &AdblockMojoInterfaceImpl::ProcessResponseHeaders, ++ weak_ptr_factory_.GetWeakPtr(), response_url, render_frame_id, headers, ++ user_agent, std::move(callback))); ++ return; ++ } ++ ++ auto* classification_runner = ++ ResourceClassificationRunnerFactory::GetForBrowserContext( ++ process_host->GetBrowserContext()); ++ DCHECK(classification_runner); ++ classification_runner->CheckResponseFilterMatch( ++ subscription_service->GetCurrentSnapshot(), response_url, ++ render_process_id_, render_frame_id, headers, ++ base::BindOnce( ++ &AdblockMojoInterfaceImpl::OnResponseHeadersClassified, ++ weak_ptr_factory_.GetWeakPtr(), response_url, render_frame_id, ++ headers, user_agent, ++ base::BindOnce( ++ &AdblockMojoInterfaceImpl::PostResponseHeadersCallbackToUI, ++ weak_ptr_factory_.GetWeakPtr(), std::move(callback)))); ++} ++ ++void AdblockMojoInterfaceImpl::OnRequestUrlClassified( ++ const GURL& request_url, ++ int32_t render_frame_id, ++ int32_t resource_type, ++ CheckFilterMatchCallback callback, ++ adblock::mojom::FilterMatchResult result) { ++ if (result == mojom::FilterMatchResult::kBlockRule) { ++ content::RenderProcessHost* process_host = ++ content::RenderProcessHost::FromID(render_process_id_); ++ if (process_host) { ++ adblock::ElementHider* element_hider = ++ adblock::ElementHiderFactory::GetForBrowserContext( ++ process_host->GetBrowserContext()); ++ const auto adblock_resource_type = ++ utils::ConvertToAdblockResourceType(request_url, resource_type); ++ if (element_hider->IsElementTypeHideable(adblock_resource_type)) { ++ element_hider->HideBlockedElement( ++ request_url, content::RenderFrameHost::FromID(render_process_id_, ++ render_frame_id)); ++ } ++ } ++ } ++ PostFilterMatchCallbackToUI(std::move(callback), result); ++} ++ ++void AdblockMojoInterfaceImpl::OnResponseHeadersClassified( ++ const GURL& response_url, ++ int32_t render_frame_id, ++ const scoped_refptr& headers, ++ const std::string& user_agent, ++ mojom::AdblockInterface::ProcessResponseHeadersCallback callback, ++ mojom::FilterMatchResult result) { ++ content::RenderProcessHost* process_host = ++ content::RenderProcessHost::FromID(render_process_id_); ++ if (!process_host || result == mojom::FilterMatchResult::kDisabled) { ++ PostResponseHeadersCallbackToUI(std::move(callback), result, nullptr); ++ return; ++ } ++ ++ if (result == mojom::FilterMatchResult::kBlockRule) { ++ adblock::ElementHider* element_hider = ++ adblock::ElementHiderFactory::GetForBrowserContext( ++ process_host->GetBrowserContext()); ++ auto adblock_resource_type = utils::DetectResourceType(response_url); ++ if (element_hider->IsElementTypeHideable(adblock_resource_type)) { ++ element_hider->HideBlockedElement( ++ response_url, content::RenderFrameHost::FromID(render_process_id_, ++ render_frame_id)); ++ } ++ PostResponseHeadersCallbackToUI(std::move(callback), result, nullptr); ++ return; ++ } ++ ++ auto* sitekey_storage = SitekeyStorageFactory::GetForBrowserContext( ++ process_host->GetBrowserContext()); ++ DCHECK(sitekey_storage); ++ sitekey_storage->ProcessResponseHeaders(response_url, headers, user_agent); ++ ++ auto* csp_injector = ++ ContentSecurityPolicyInjectorFactory::GetForBrowserContext( ++ process_host->GetBrowserContext()); ++ DCHECK(csp_injector); ++ csp_injector->InsertContentSecurityPolicyHeadersIfApplicable( ++ response_url, ++ content::GlobalRenderFrameHostId(render_process_id_, render_frame_id), ++ headers, base::BindOnce(std::move(callback), result)); ++} ++ ++void AdblockMojoInterfaceImpl::CheckRewriteFilterMatch( ++ const GURL& request_url, ++ int32_t render_frame_id, ++ mojom::AdblockInterface::CheckRewriteFilterMatchCallback callback) { ++ content::RenderProcessHost* process_host = ++ content::RenderProcessHost::FromID(render_process_id_); ++ if (!process_host) { ++ PostRewriteCallbackToUI(std::move(callback), absl::optional{}); ++ return; ++ } ++ ++ auto* subscription_service = GetSubscriptionService(process_host); ++ if (!subscription_service->IsInitialized()) { ++ subscription_service->RunWhenInitialized( ++ base::BindOnce(&AdblockMojoInterfaceImpl::CheckRewriteFilterMatch, ++ weak_ptr_factory_.GetWeakPtr(), request_url, ++ render_frame_id, std::move(callback))); ++ return; ++ } ++ ++ auto* classification_runner = ++ adblock::ResourceClassificationRunnerFactory::GetForBrowserContext( ++ process_host->GetBrowserContext()); ++ DCHECK(classification_runner); ++ classification_runner->CheckRewriteFilterMatch( ++ subscription_service->GetCurrentSnapshot(), request_url, ++ render_process_id_, render_frame_id, ++ base::BindOnce(&AdblockMojoInterfaceImpl::PostRewriteCallbackToUI, ++ weak_ptr_factory_.GetWeakPtr(), std::move(callback))); ++} ++ ++void AdblockMojoInterfaceImpl::Clone( ++ mojo::PendingReceiver receiver) { ++ receivers_.Add(this, std::move(receiver)); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/adblock_mojo_interface_impl.h b/chrome/browser/adblock/adblock_mojo_interface_impl.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_mojo_interface_impl.h +@@ -0,0 +1,86 @@ ++/* ++ * 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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_MOJO_INTERFACE_IMPL_H_ ++#define CHROME_BROWSER_ADBLOCK_ADBLOCK_MOJO_INTERFACE_IMPL_H_ ++ ++#include "components/adblock/content/browser/adblock_content_utils.h" ++#include "components/adblock/content/common/mojom/adblock.mojom.h" ++ ++#include "mojo/public/cpp/bindings/receiver_set.h" ++ ++class GURL; ++ ++namespace adblock { ++/** ++ * @brief Implements mojo interface so that renderer can call filter engine ++ * through the browser process ++ * ++ */ ++class AdblockMojoInterfaceImpl final : public mojom::AdblockInterface { ++ public: ++ explicit AdblockMojoInterfaceImpl(int32_t render_process_id); ++ ~AdblockMojoInterfaceImpl() final; ++ void CheckFilterMatch( ++ const GURL& request_url, ++ int32_t resource_type, ++ int32_t render_frame_id, ++ mojom::AdblockInterface::CheckFilterMatchCallback cb) final; ++ void Clone(mojo::PendingReceiver receiver) final; ++ void ProcessResponseHeaders( ++ const GURL& request_url, ++ int32_t render_frame_id, ++ const scoped_refptr& headers, ++ const std::string& user_agent, ++ mojom::AdblockInterface::ProcessResponseHeadersCallback cb) final; ++ void CheckRewriteFilterMatch( ++ const ::GURL& request_url, ++ int32_t render_frame_id, ++ mojom::AdblockInterface::CheckRewriteFilterMatchCallback callback) final; ++ ++ private: ++ void OnRequestUrlClassified( ++ const GURL& request_url, ++ int32_t render_frame_id, ++ int32_t resource_type, ++ mojom::AdblockInterface::CheckFilterMatchCallback callback, ++ adblock::mojom::FilterMatchResult result); ++ void OnResponseHeadersClassified( ++ const GURL& response_url, ++ int32_t render_frame_id, ++ const scoped_refptr& headers, ++ const std::string& user_agent, ++ mojom::AdblockInterface::ProcessResponseHeadersCallback callback, ++ adblock::mojom::FilterMatchResult result); ++ void PostFilterMatchCallbackToUI( ++ mojom::AdblockInterface::CheckFilterMatchCallback callback, ++ mojom::FilterMatchResult result); ++ void PostResponseHeadersCallbackToUI( ++ mojom::AdblockInterface::ProcessResponseHeadersCallback callback, ++ mojom::FilterMatchResult result, ++ network::mojom::ParsedHeadersPtr parsed_headers); ++ void PostRewriteCallbackToUI( ++ base::OnceCallback&)> callback, ++ const absl::optional& url); ++ int32_t render_process_id_; ++ mojo::ReceiverSet receivers_; ++ base::WeakPtrFactory weak_ptr_factory_{this}; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_MOJO_INTERFACE_IMPL_H_ +diff --git a/chrome/browser/adblock/adblock_mojo_interface_impl_unittest.cc b/chrome/browser/adblock/adblock_mojo_interface_impl_unittest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_mojo_interface_impl_unittest.cc +@@ -0,0 +1,605 @@ ++/* ++ * 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 . ++ */ ++ ++#include "chrome/browser/adblock/adblock_mojo_interface_impl.h" ++ ++#include ++#include ++ ++#include "base/bind.h" ++#include "base/memory/raw_ptr.h" ++#include "base/test/bind.h" ++#include "base/test/mock_callback.h" ++#include "chrome/browser/adblock/content_security_policy_injector_factory.h" ++#include "chrome/browser/adblock/element_hider_factory.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/adblock/sitekey_storage_factory.h" ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/test/base/chrome_render_view_host_test_harness.h" ++#include "components/adblock/content/browser/adblock_content_utils.h" ++#include "components/adblock/content/browser/element_hider.h" ++#include "components/adblock/content/browser/test/mock_adblock_content_security_policy_injector.h" ++#include "components/adblock/content/browser/test/mock_element_hider.h" ++#include "components/adblock/content/browser/test/mock_resource_classification_runner.h" ++#include "components/adblock/core/subscription/test/mock_subscription_collection.h" ++#include "components/adblock/core/subscription/test/mock_subscription_service.h" ++#include "components/adblock/core/test/mock_sitekey_storage.h" ++#include "content/public/browser/render_process_host.h" ++#include "content/public/browser/web_contents.h" ++#include "net/http/http_response_headers.h" ++#include "services/network/public/mojom/parsed_headers.mojom.h" ++#include "testing/gmock/include/gmock/gmock.h" ++#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" ++#include "url/gurl.h" ++ ++using testing::_; ++using testing::Return; ++using MockCheckFilterMatchCallback = base::MockCallback< ++ adblock::mojom::AdblockInterface::CheckFilterMatchCallback>; ++using MockProcessResponseHeadersCallback = base::MockCallback< ++ adblock::mojom::AdblockInterface::ProcessResponseHeadersCallback>; ++ ++namespace { ++ ++static BrowserContextKeyedServiceFactory::TestingFactory ++AdblockResourceClassificationRunnerTestingFactory() { ++ return base::BindRepeating( ++ [](content::BrowserContext* context) -> std::unique_ptr { ++ return std::make_unique(); ++ }); ++} ++ ++static BrowserContextKeyedServiceFactory::TestingFactory ++SitekeyStorageTestingFactory() { ++ return base::BindRepeating( ++ [](content::BrowserContext* context) -> std::unique_ptr { ++ return std::make_unique(); ++ }); ++} ++ ++static BrowserContextKeyedServiceFactory::TestingFactory ++AdblockContentSecurityPolicyInjectorTestingFactory() { ++ return base::BindRepeating( ++ [](content::BrowserContext* context) -> std::unique_ptr { ++ return std::make_unique< ++ adblock::MockAdblockContentSecurityPolicyInjector>(); ++ }); ++} ++ ++static BrowserContextKeyedServiceFactory::TestingFactory ++ElementHiderFactoryTestingFactory() { ++ return base::BindRepeating( ++ [](content::BrowserContext* context) -> std::unique_ptr { ++ return std::make_unique(); ++ }); ++} ++ ++static BrowserContextKeyedServiceFactory::TestingFactory ++SubscriptionServiceTestingFactory() { ++ return base::BindRepeating( ++ [](content::BrowserContext* context) -> std::unique_ptr { ++ return std::make_unique(); ++ }); ++} ++ ++enum class SubscriptionServiceInitialState { Initialized, NotInitialized }; ++ ++} // namespace ++ ++namespace adblock { ++ ++class AdblockMojoInterfaceImplTest : public ChromeRenderViewHostTestHarness { ++ public: ++ void SetUp() override { ++ ChromeRenderViewHostTestHarness::SetUp(); ++ ++ mock_resource_classification_runner_ = ++ static_cast( ++ ResourceClassificationRunnerFactory::GetInstance() ++ ->SetTestingFactoryAndUse( ++ browser_context(), ++ AdblockResourceClassificationRunnerTestingFactory())); ++ ++ mock_sitekey_storage_ = static_cast( ++ SitekeyStorageFactory::GetInstance()->SetTestingFactoryAndUse( ++ browser_context(), SitekeyStorageTestingFactory())); ++ ++ mock_csp_injector_ = static_cast( ++ ContentSecurityPolicyInjectorFactory::GetInstance() ++ ->SetTestingFactoryAndUse( ++ browser_context(), ++ AdblockContentSecurityPolicyInjectorTestingFactory())); ++ ++ mock_element_hider_ = static_cast( ++ ElementHiderFactory::GetInstance()->SetTestingFactoryAndUse( ++ browser_context(), ElementHiderFactoryTestingFactory())); ++ ++ mock_subscription_service_ = static_cast( ++ SubscriptionServiceFactory::GetInstance()->SetTestingFactoryAndUse( ++ browser_context(), SubscriptionServiceTestingFactory())); ++ } ++ ++ void InitializeSubscriptionService() { ++ EXPECT_CALL(*mock_subscription_service_, IsInitialized()) ++ .WillRepeatedly(Return(true)); ++ EXPECT_CALL(*mock_subscription_service_, GetCurrentSnapshot()) ++ .WillRepeatedly( ++ []() { return std::make_unique(); }); ++ for (auto& task : deferred_tasks_) { ++ std::move(task).Run(); ++ } ++ } ++ ++ void SetSubscriptionServiceInitialState( ++ SubscriptionServiceInitialState state) { ++ EXPECT_CALL(*mock_subscription_service_, IsInitialized()) ++ .WillRepeatedly(testing::Return( ++ state == SubscriptionServiceInitialState::Initialized)); ++ if (state == SubscriptionServiceInitialState::NotInitialized) { ++ // When the SubscriptionService is not initialized, testee will defer ++ // tasks to run after it becomes initialized via RunWhenInitialized(). ++ // Remember those tasks, we will run them in ++ // EnsureSubscriptionServiceInitialized(). ++ EXPECT_CALL(*mock_subscription_service_, RunWhenInitialized(_)) ++ .WillRepeatedly([&](base::OnceClosure task) { ++ deferred_tasks_.push_back(std::move(task)); ++ }); ++ } ++ } ++ ++ void TearDown() override { ChromeRenderViewHostTestHarness::TearDown(); } ++ ++ TestingProfile::TestingFactories GetTestingFactories() const override { ++ return {{ResourceClassificationRunnerFactory::GetInstance(), ++ AdblockResourceClassificationRunnerTestingFactory()}}; ++ } ++ ++ static constexpr int INVALID_RENDER_PROCESS_ID = 42; ++ static constexpr int DUMMY_RENDER_FRAME_ID = 42; ++ static constexpr int DUMMY_RESOURCE_TYPE = 42; ++ ++ raw_ptr ++ mock_resource_classification_runner_; ++ raw_ptr mock_sitekey_storage_; ++ raw_ptr mock_csp_injector_; ++ raw_ptr mock_element_hider_; ++ raw_ptr mock_subscription_service_; ++ std::vector deferred_tasks_; ++}; ++ ++TEST_F(AdblockMojoInterfaceImplTest, CheckFilterMatch) { ++ MockCheckFilterMatchCallback callback; ++ mojom::AdblockInterface::CheckFilterMatchCallback callback_captured_by_rq; ++ const GURL request_url("https://request_url.com"); ++ ++ InitializeSubscriptionService(); ++ EXPECT_CALL(*mock_resource_classification_runner_, ++ CheckRequestFilterMatch(_, request_url, DUMMY_RESOURCE_TYPE, ++ main_rfh()->GetProcess()->GetID(), ++ main_rfh()->GetRoutingID(), _)) ++ .Times(1) ++ .WillOnce([&](auto, const GURL&, int32_t, int32_t, int32_t, ++ mojom::AdblockInterface::CheckFilterMatchCallback cb) { ++ callback_captured_by_rq = std::move(cb); ++ }); ++ ++ auto adblock_mojo_interface = std::make_unique( ++ main_rfh()->GetProcess()->GetID()); ++ adblock_mojo_interface->CheckFilterMatch(request_url, DUMMY_RESOURCE_TYPE, ++ main_rfh()->GetRoutingID(), ++ callback.Get()); ++ ++ // |callback| ran in response to ResourceClassificationRunner running ++ // |callback_captured_by_rq|. ++ EXPECT_CALL(callback, Run(mojom::FilterMatchResult::kAllowRule)).Times(1); ++ std::move(callback_captured_by_rq).Run(mojom::FilterMatchResult::kAllowRule); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, ChecktFilterMatchDeferred) { ++ MockCheckFilterMatchCallback callback; ++ mojom::AdblockInterface::CheckFilterMatchCallback callback_captured_by_rq; ++ const GURL request_url("https://request_url.com"); ++ ++ SetSubscriptionServiceInitialState( ++ SubscriptionServiceInitialState::NotInitialized); ++ ++ EXPECT_CALL(*mock_resource_classification_runner_, ++ CheckRequestFilterMatch(_, request_url, DUMMY_RESOURCE_TYPE, ++ main_rfh()->GetProcess()->GetID(), ++ main_rfh()->GetRoutingID(), _)) ++ .Times(1) ++ .WillOnce([&](auto, const GURL&, int32_t, int32_t, int32_t, ++ mojom::AdblockInterface::CheckFilterMatchCallback cb) { ++ callback_captured_by_rq = std::move(cb); ++ }); ++ ++ auto adblock_mojo_interface = std::make_unique( ++ main_rfh()->GetProcess()->GetID()); ++ adblock_mojo_interface->CheckFilterMatch(request_url, DUMMY_RESOURCE_TYPE, ++ main_rfh()->GetRoutingID(), ++ callback.Get()); ++ ++ InitializeSubscriptionService(); ++ // |callback| ran in response to ResourceClassificationRunner running ++ // |callback_captured_by_rq|. ++ EXPECT_CALL(callback, Run(mojom::FilterMatchResult::kAllowRule)).Times(1); ++ std::move(callback_captured_by_rq).Run(mojom::FilterMatchResult::kAllowRule); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, CheckFilterMatchNoProcessHost) { ++ MockCheckFilterMatchCallback callback; ++ const GURL request_url("https://request_url.com"); ++ ++ InitializeSubscriptionService(); ++ EXPECT_CALL(*mock_resource_classification_runner_, ++ CheckRequestFilterMatch(_, _, _, _, _, _)) ++ .Times(0); ++ EXPECT_CALL(callback, Run(mojom::FilterMatchResult::kNoRule)).Times(1); ++ ++ auto adblock_mojo_interface = ++ std::make_unique(INVALID_RENDER_PROCESS_ID); ++ adblock_mojo_interface->CheckFilterMatch( ++ request_url, DUMMY_RESOURCE_TYPE, DUMMY_RENDER_FRAME_ID, callback.Get()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, ++ ChecktFilterMatch_RenderFrameHostDiesWhileTaskDeferred) { ++ MockCheckFilterMatchCallback callback; ++ const GURL request_url("https://request_url.com"); ++ ++ SetSubscriptionServiceInitialState( ++ SubscriptionServiceInitialState::NotInitialized); ++ ++ EXPECT_CALL(callback, Run(mojom::FilterMatchResult::kNoRule)).Times(1); ++ ++ auto adblock_mojo_interface = std::make_unique( ++ main_rfh()->GetProcess()->GetID()); ++ adblock_mojo_interface->CheckFilterMatch(request_url, DUMMY_RESOURCE_TYPE, ++ main_rfh()->GetRoutingID(), ++ callback.Get()); ++ ++ DeleteContents(); ++ ++ InitializeSubscriptionService(); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, ++ ProcessResponseHeaders_BlockedWithHeaderFilter) { ++ MockProcessResponseHeadersCallback callback; ++ const GURL response_url("https://request_url.com"); ++ auto headers = net::HttpResponseHeaders::TryToCreate(""); ++ auto headers_filter_result = mojom::FilterMatchResult::kBlockRule; ++ auto render_frame_host_id = main_rfh()->GetRoutingID(); ++ ++ mojom::AdblockInterface::ProcessResponseHeadersCallback ++ callback_captured_by_csp_injector; ++ mojom::AdblockInterface::CheckFilterMatchCallback ++ continue_process_response_headers_callback; ++ ++ InitializeSubscriptionService(); ++ EXPECT_CALL(*mock_resource_classification_runner_, ++ CheckResponseFilterMatch(_, response_url, _, ++ main_rfh()->GetRoutingID(), headers, _)) ++ .WillOnce([&](auto, const GURL&, int32_t process_id, ++ int32_t render_frame_id, ++ const scoped_refptr&, ++ mojom::AdblockInterface::CheckFilterMatchCallback cb) { ++ continue_process_response_headers_callback = std::move(cb); ++ }); ++ // Sitekey and CSP Injector will not be called because the response was ++ // blocked entirely. ++ EXPECT_CALL(*mock_sitekey_storage_, ProcessResponseHeaders(_, _, _)).Times(0); ++ EXPECT_CALL(*mock_csp_injector_, ++ InsertContentSecurityPolicyHeadersIfApplicable(_, _, _, _)) ++ .Times(0); ++ ++ auto adblock_mojo_interface = std::make_unique( ++ main_rfh()->GetProcess()->GetID()); ++ adblock_mojo_interface->ProcessResponseHeaders( ++ response_url, render_frame_host_id, headers, "", callback.Get()); ++ ++ EXPECT_CALL(callback, Run(headers_filter_result, testing::IsFalse())) ++ .Times(1); ++ std::move(continue_process_response_headers_callback) ++ .Run(headers_filter_result); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, ProcessResponseHeaders_CspInjection) { ++ MockProcessResponseHeadersCallback callback; ++ const GURL response_url("https://request_url.com"); ++ auto headers = net::HttpResponseHeaders::TryToCreate(""); ++ auto headers_filter_result = mojom::FilterMatchResult::kNoRule; ++ ++ mojom::AdblockInterface::CheckFilterMatchCallback ++ continue_process_response_headers_callback; ++ ++ InitializeSubscriptionService(); ++ EXPECT_CALL(*mock_resource_classification_runner_, ++ CheckResponseFilterMatch(_, response_url, _, ++ main_rfh()->GetRoutingID(), _, _)) ++ .WillOnce([&](auto, const GURL&, int32_t process_id, ++ int32_t render_frame_id, ++ const scoped_refptr&, ++ mojom::AdblockInterface::CheckFilterMatchCallback cb) { ++ continue_process_response_headers_callback = std::move(cb); ++ }); ++ auto adblock_mojo_interface = std::make_unique( ++ main_rfh()->GetProcess()->GetID()); ++ adblock_mojo_interface->ProcessResponseHeaders( ++ response_url, main_rfh()->GetRoutingID(), headers, "", callback.Get()); ++ ++ InsertContentSecurityPolicyHeadersCallback callback_captured_by_csp_injector; ++ ++ EXPECT_CALL(*mock_sitekey_storage_, ++ ProcessResponseHeaders(response_url, headers, "")) ++ .Times(1); ++ EXPECT_CALL( ++ *mock_csp_injector_, ++ InsertContentSecurityPolicyHeadersIfApplicable( ++ response_url, ++ content::GlobalRenderFrameHostId(main_rfh()->GetProcess()->GetID(), ++ main_rfh()->GetRoutingID()), ++ headers, _)) ++ .Times(1) ++ .WillOnce([&](const GURL&, content::GlobalRenderFrameHostId, ++ const scoped_refptr&, ++ InsertContentSecurityPolicyHeadersCallback cb) { ++ callback_captured_by_csp_injector = std::move(cb); ++ }); ++ std::move(continue_process_response_headers_callback) ++ .Run(headers_filter_result); ++ ++ // |callback| ran in response to ContentPolicySecurityInjector running ++ // |callback_captured_by_csp_injector|. ++ EXPECT_CALL(callback, Run(headers_filter_result, testing::IsFalse())) ++ .Times(1); ++ std::move(callback_captured_by_csp_injector) ++ .Run(mojo::StructPtr()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, ProcessResponseHeadersNoProcessHost) { ++ MockProcessResponseHeadersCallback callback; ++ const GURL response_url("https://request_url.com"); ++ auto headers = net::HttpResponseHeaders::TryToCreate(""); ++ ++ InitializeSubscriptionService(); ++ EXPECT_CALL(*mock_sitekey_storage_, ProcessResponseHeaders(_, _, _)).Times(0); ++ EXPECT_CALL(*mock_csp_injector_, ++ InsertContentSecurityPolicyHeadersIfApplicable(_, _, _, _)) ++ .Times(0); ++ EXPECT_CALL(callback, Run(_, _)).Times(1); ++ ++ auto adblock_mojo_interface = ++ std::make_unique(INVALID_RENDER_PROCESS_ID); ++ adblock_mojo_interface->ProcessResponseHeaders( ++ response_url, DUMMY_RENDER_FRAME_ID, headers, "", callback.Get()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, ElementHiding_BlockedRequestHidden) { ++ MockCheckFilterMatchCallback mock_check_filter_match_callback; ++ const GURL request_url("https://request_url.com"); ++ auto resource_type = static_cast(blink::mojom::ResourceType::kImage); ++ auto classification_result = mojom::FilterMatchResult::kBlockRule; ++ ++ InitializeSubscriptionService(); ++ EXPECT_CALL(*mock_element_hider_, IsElementTypeHideable(ContentType::Image)) ++ .Times(1) ++ .WillOnce(testing::Return(true)); ++ EXPECT_CALL(*mock_element_hider_, HideBlockedElement(request_url, _)) ++ .Times(1); ++ ++ EXPECT_CALL(*mock_resource_classification_runner_, ++ CheckRequestFilterMatch(_, request_url, resource_type, ++ main_rfh()->GetProcess()->GetID(), ++ main_rfh()->GetRoutingID(), _)) ++ .WillOnce([&](auto, const GURL&, int32_t resource_type, ++ int32_t process_id, int32_t render_frame_id, ++ mojom::AdblockInterface::CheckFilterMatchCallback cb) { ++ std::move(cb).Run(classification_result); ++ }); ++ ++ auto adblock_mojo_interface = std::make_unique( ++ main_rfh()->GetProcess()->GetID()); ++ ++ adblock_mojo_interface->CheckFilterMatch( ++ request_url, resource_type, main_rfh()->GetRoutingID(), ++ mock_check_filter_match_callback.Get()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, ElementHiding_RequestNotHideable) { ++ MockCheckFilterMatchCallback mock_check_filter_match_callback; ++ const GURL request_url("https://request_url.com"); ++ auto resource_type = static_cast(blink::mojom::ResourceType::kPing); ++ auto classification_result = mojom::FilterMatchResult::kBlockRule; ++ ++ InitializeSubscriptionService(); ++ EXPECT_CALL(*mock_element_hider_, IsElementTypeHideable(ContentType::Ping)) ++ .Times(1) ++ .WillOnce(testing::Return(false)); ++ EXPECT_CALL(*mock_element_hider_, HideBlockedElement(request_url, _)) ++ .Times(0); ++ ++ EXPECT_CALL(*mock_resource_classification_runner_, ++ CheckRequestFilterMatch(_, request_url, resource_type, ++ main_rfh()->GetProcess()->GetID(), ++ main_rfh()->GetRoutingID(), _)) ++ .WillOnce([&](auto, const GURL&, int32_t resource_type, ++ int32_t process_id, int32_t render_frame_id, ++ mojom::AdblockInterface::CheckFilterMatchCallback cb) { ++ std::move(cb).Run(classification_result); ++ }); ++ ++ auto adblock_mojo_interface = std::make_unique( ++ main_rfh()->GetProcess()->GetID()); ++ ++ adblock_mojo_interface->CheckFilterMatch( ++ request_url, resource_type, main_rfh()->GetRoutingID(), ++ mock_check_filter_match_callback.Get()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, ElementHiding_AllowedRequestNotHidden) { ++ MockCheckFilterMatchCallback mock_check_filter_match_callback; ++ const GURL request_url("https://request_url.com"); ++ auto resource_type = static_cast(blink::mojom::ResourceType::kImage); ++ auto classification_result = mojom::FilterMatchResult::kAllowRule; ++ ++ InitializeSubscriptionService(); ++ EXPECT_CALL(*mock_element_hider_, IsElementTypeHideable(ContentType::Image)) ++ .Times(0); ++ EXPECT_CALL(*mock_element_hider_, HideBlockedElement(request_url, _)) ++ .Times(0); ++ ++ EXPECT_CALL(*mock_resource_classification_runner_, ++ CheckRequestFilterMatch(_, request_url, resource_type, ++ main_rfh()->GetProcess()->GetID(), ++ main_rfh()->GetRoutingID(), _)) ++ .WillOnce([&](auto, const GURL&, int32_t resource_type, ++ int32_t process_id, int32_t render_frame_id, ++ mojom::AdblockInterface::CheckFilterMatchCallback cb) { ++ std::move(cb).Run(classification_result); ++ }); ++ ++ auto adblock_mojo_interface = std::make_unique( ++ main_rfh()->GetProcess()->GetID()); ++ ++ adblock_mojo_interface->CheckFilterMatch( ++ request_url, resource_type, main_rfh()->GetRoutingID(), ++ mock_check_filter_match_callback.Get()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, ElementHiding_BlockedResponseHidden) { ++ MockProcessResponseHeadersCallback mock_process_response_headers_callback; ++ const GURL response_url("https://request_url.com/image.png"); ++ auto headers = net::HttpResponseHeaders::TryToCreate(""); ++ auto classification_result = mojom::FilterMatchResult::kBlockRule; ++ ++ InitializeSubscriptionService(); ++ EXPECT_CALL(*mock_element_hider_, IsElementTypeHideable(ContentType::Image)) ++ .Times(1) ++ .WillOnce(testing::Return(true)); ++ EXPECT_CALL(*mock_element_hider_, HideBlockedElement(response_url, _)) ++ .Times(1); ++ ++ EXPECT_CALL(*mock_resource_classification_runner_, ++ CheckResponseFilterMatch(_, response_url, ++ main_rfh()->GetProcess()->GetID(), ++ main_rfh()->GetRoutingID(), _, _)) ++ .WillOnce([&](auto, const GURL&, int32_t process_id, ++ int32_t render_frame_id, ++ const scoped_refptr&, ++ mojom::AdblockInterface::CheckFilterMatchCallback cb) { ++ std::move(cb).Run(classification_result); ++ }); ++ ++ auto adblock_mojo_interface = std::make_unique( ++ main_rfh()->GetProcess()->GetID()); ++ ++ adblock_mojo_interface->ProcessResponseHeaders( ++ response_url, main_rfh()->GetRoutingID(), headers, "", ++ mock_process_response_headers_callback.Get()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, ElementHiding_ResponseNotHideable) { ++ MockProcessResponseHeadersCallback mock_process_response_headers_callback; ++ const GURL response_url("https://request_url.com/script.js"); ++ auto headers = net::HttpResponseHeaders::TryToCreate(""); ++ auto classification_result = mojom::FilterMatchResult::kBlockRule; ++ ++ InitializeSubscriptionService(); ++ EXPECT_CALL(*mock_element_hider_, IsElementTypeHideable(ContentType::Script)) ++ .Times(1) ++ .WillOnce(testing::Return(false)); ++ EXPECT_CALL(*mock_element_hider_, HideBlockedElement(response_url, _)) ++ .Times(0); ++ ++ EXPECT_CALL(*mock_resource_classification_runner_, ++ CheckResponseFilterMatch(_, response_url, ++ main_rfh()->GetProcess()->GetID(), ++ main_rfh()->GetRoutingID(), _, _)) ++ .WillOnce([&](auto, const GURL&, int32_t process_id, ++ int32_t render_frame_id, ++ const scoped_refptr&, ++ mojom::AdblockInterface::CheckFilterMatchCallback cb) { ++ std::move(cb).Run(classification_result); ++ }); ++ ++ auto adblock_mojo_interface = std::make_unique( ++ main_rfh()->GetProcess()->GetID()); ++ ++ adblock_mojo_interface->ProcessResponseHeaders( ++ response_url, main_rfh()->GetRoutingID(), headers, "", ++ mock_process_response_headers_callback.Get()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++TEST_F(AdblockMojoInterfaceImplTest, ElementHiding_AllowedResponseNotHidden) { ++ MockProcessResponseHeadersCallback mock_process_response_headers_callback; ++ const GURL response_url("https://request_url.com/image.png"); ++ auto headers = net::HttpResponseHeaders::TryToCreate(""); ++ auto classification_result = mojom::FilterMatchResult::kAllowRule; ++ ++ InitializeSubscriptionService(); ++ EXPECT_CALL(*mock_element_hider_, IsElementTypeHideable(ContentType::Image)) ++ .Times(0); ++ EXPECT_CALL(*mock_element_hider_, HideBlockedElement(response_url, _)) ++ .Times(0); ++ ++ EXPECT_CALL(*mock_resource_classification_runner_, ++ CheckResponseFilterMatch(_, response_url, ++ main_rfh()->GetProcess()->GetID(), ++ main_rfh()->GetRoutingID(), _, _)) ++ .WillOnce([&](auto, const GURL&, int32_t process_id, ++ int32_t render_frame_id, ++ const scoped_refptr&, ++ mojom::AdblockInterface::CheckFilterMatchCallback cb) { ++ std::move(cb).Run(classification_result); ++ }); ++ ++ auto adblock_mojo_interface = std::make_unique( ++ main_rfh()->GetProcess()->GetID()); ++ ++ adblock_mojo_interface->ProcessResponseHeaders( ++ response_url, main_rfh()->GetRoutingID(), headers, "", ++ mock_process_response_headers_callback.Get()); ++ ++ task_environment()->RunUntilIdle(); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/adblock_telemetry_service_factory.cc b/chrome/browser/adblock/adblock_telemetry_service_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_telemetry_service_factory.cc +@@ -0,0 +1,91 @@ ++/* ++ * 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 . ++ */ ++ ++#include "chrome/browser/adblock/adblock_telemetry_service_factory.h" ++ ++#include ++ ++#include "base/no_destructor.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "chrome/common/pref_names.h" ++#include "components/adblock/core/activeping_telemetry_topic_provider.h" ++#include "components/adblock/core/adblock_telemetry_service.h" ++#include "components/adblock/core/common/adblock_utils.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/storage_partition.h" ++ ++namespace adblock { ++ ++// static ++AdblockTelemetryService* AdblockTelemetryServiceFactory::GetForProfile( ++ Profile* profile) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(profile, true)); ++} ++// static ++AdblockTelemetryServiceFactory* AdblockTelemetryServiceFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++AdblockTelemetryServiceFactory::AdblockTelemetryServiceFactory() ++ : BrowserContextKeyedServiceFactory( ++ "AdblockTelemetryService", ++ BrowserContextDependencyManager::GetInstance()) {} ++ ++AdblockTelemetryServiceFactory::~AdblockTelemetryServiceFactory() = default; ++ ++KeyedService* AdblockTelemetryServiceFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ // Need to use a URLLoaderFactory specific to the browser context, not from ++ // system_network_context_manager(), because the required Accept-Language ++ // header depends on user's language settings and is not present in requests ++ // made from the System network context. ++ scoped_refptr url_loader_factory = ++ context->GetDefaultStoragePartition() ++ ->GetURLLoaderFactoryForBrowserProcess(); ++ auto* prefs = Profile::FromBrowserContext(context)->GetPrefs(); ++ auto service = ++ std::make_unique(prefs, url_loader_factory); ++ ++ service->AddTopicProvider(std::make_unique( ++ utils::GetAppInfo(), prefs, ++ ActivepingTelemetryTopicProvider::DefaultBaseUrl(), ++ ActivepingTelemetryTopicProvider::DefaultAuthToken())); ++ ++ if (url_loader_factory) ++ service->Start(); ++ ++ return service.release(); ++} ++ ++content::BrowserContext* AdblockTelemetryServiceFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++bool AdblockTelemetryServiceFactory::ServiceIsNULLWhileTesting() const { ++ return true; ++} ++ ++bool AdblockTelemetryServiceFactory::ServiceIsCreatedWithBrowserContext() ++ const { ++ return true; ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/adblock_telemetry_service_factory.h b/chrome/browser/adblock/adblock_telemetry_service_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/adblock_telemetry_service_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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ ++ ++#include "base/no_destructor.h" ++#include "components/keyed_service/content/browser_context_keyed_service_factory.h" ++ ++class Profile; ++ ++namespace adblock { ++class AdblockTelemetryService; ++class AdblockTelemetryServiceFactory ++ : public BrowserContextKeyedServiceFactory { ++ public: ++ static AdblockTelemetryService* GetForProfile(Profile* profile); ++ static AdblockTelemetryServiceFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ AdblockTelemetryServiceFactory(); ++ ~AdblockTelemetryServiceFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++ bool ServiceIsNULLWhileTesting() const override; ++ bool ServiceIsCreatedWithBrowserContext() const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_ +diff --git a/chrome/browser/adblock/content_security_policy_injector_factory.cc b/chrome/browser/adblock/content_security_policy_injector_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/content_security_policy_injector_factory.cc +@@ -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 . ++ */ ++ ++#include "chrome/browser/adblock/content_security_policy_injector_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/content/browser/content_security_policy_injector_impl.h" ++#include "components/adblock/content/browser/frame_hierarchy_builder.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++ContentSecurityPolicyInjector* ++ContentSecurityPolicyInjectorFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++ContentSecurityPolicyInjectorFactory* ++ContentSecurityPolicyInjectorFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++ContentSecurityPolicyInjectorFactory::ContentSecurityPolicyInjectorFactory() ++ : BrowserContextKeyedServiceFactory( ++ "ContentSecurityPolicyInjector", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(SubscriptionServiceFactory::GetInstance()); ++} ++ ++ContentSecurityPolicyInjectorFactory::~ContentSecurityPolicyInjectorFactory() = ++ default; ++ ++KeyedService* ContentSecurityPolicyInjectorFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new ContentSecurityPolicyInjectorImpl( ++ SubscriptionServiceFactory::GetForBrowserContext(context), ++ std::make_unique()); ++} ++ ++content::BrowserContext* ++ContentSecurityPolicyInjectorFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/content_security_policy_injector_factory.h b/chrome/browser/adblock/content_security_policy_injector_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/content_security_policy_injector_factory.h +@@ -0,0 +1,49 @@ ++/* ++ * 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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_CONTENT_SECURITY_POLICY_INJECTOR_H_ ++#define CHROME_BROWSER_ADBLOCK_CONTENT_SECURITY_POLICY_INJECTOR_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 ContentSecurityPolicyInjector; ++class ContentSecurityPolicyInjectorFactory ++ : public BrowserContextKeyedServiceFactory { ++ public: ++ static ContentSecurityPolicyInjector* GetForBrowserContext( ++ content::BrowserContext* context); ++ static ContentSecurityPolicyInjectorFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ ContentSecurityPolicyInjectorFactory(); ++ ~ContentSecurityPolicyInjectorFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_CONTENT_SECURITY_POLICY_INJECTOR_H_ +diff --git a/chrome/browser/adblock/element_hider_factory.cc b/chrome/browser/adblock/element_hider_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/element_hider_factory.cc +@@ -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 . ++ */ ++ ++#include "chrome/browser/adblock/element_hider_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/content/browser/element_hider_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++ElementHider* ElementHiderFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++ElementHiderFactory* ElementHiderFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++ElementHiderFactory::ElementHiderFactory() ++ : BrowserContextKeyedServiceFactory( ++ "ElementHider", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(adblock::SubscriptionServiceFactory::GetInstance()); ++} ++ ++ElementHiderFactory::~ElementHiderFactory() = default; ++ ++KeyedService* ElementHiderFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new ElementHiderImpl( ++ adblock::SubscriptionServiceFactory::GetForBrowserContext(context)); ++} ++ ++content::BrowserContext* ElementHiderFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/element_hider_factory.h b/chrome/browser/adblock/element_hider_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/element_hider_factory.h +@@ -0,0 +1,47 @@ ++/* ++ * 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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_ELEMENT_HIDER_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_ELEMENT_HIDER_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 ElementHider; ++class ElementHiderFactory : public BrowserContextKeyedServiceFactory { ++ public: ++ static ElementHider* GetForBrowserContext(content::BrowserContext* context); ++ static ElementHiderFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ ElementHiderFactory(); ++ ~ElementHiderFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_ELEMENT_HIDER_FACTORY_H_ +diff --git a/chrome/browser/adblock/resource_classification_runner_factory.cc b/chrome/browser/adblock/resource_classification_runner_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/resource_classification_runner_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 . ++ */ ++ ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/sitekey_storage_factory.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/content/browser/frame_hierarchy_builder.h" ++#include "components/adblock/content/browser/resource_classification_runner_impl.h" ++#include "components/adblock/core/classifier/resource_classifier_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++ResourceClassificationRunner* ++ResourceClassificationRunnerFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++ResourceClassificationRunnerFactory* ++ResourceClassificationRunnerFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++ResourceClassificationRunnerFactory::ResourceClassificationRunnerFactory() ++ : BrowserContextKeyedServiceFactory( ++ "ResourceClassificationRunner", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(SitekeyStorageFactory::GetInstance()); ++} ++ ++ResourceClassificationRunnerFactory::~ResourceClassificationRunnerFactory() = ++ default; ++ ++KeyedService* ResourceClassificationRunnerFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new ResourceClassificationRunnerImpl( ++ base::MakeRefCounted(), ++ std::make_unique(), ++ SitekeyStorageFactory::GetForBrowserContext(context)); ++} ++ ++content::BrowserContext* ++ResourceClassificationRunnerFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/resource_classification_runner_factory.h b/chrome/browser/adblock/resource_classification_runner_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/resource_classification_runner_factory.h +@@ -0,0 +1,49 @@ ++/* ++ * 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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_RESOURCE_CLASSIFICATION_RUNNER_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_RESOURCE_CLASSIFICATION_RUNNER_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 ResourceClassificationRunner; ++class ResourceClassificationRunnerFactory ++ : public BrowserContextKeyedServiceFactory { ++ public: ++ static ResourceClassificationRunner* GetForBrowserContext( ++ content::BrowserContext* context); ++ static ResourceClassificationRunnerFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ ResourceClassificationRunnerFactory(); ++ ~ResourceClassificationRunnerFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_RESOURCE_CLASSIFICATION_RUNNER_FACTORY_H_ +diff --git a/chrome/browser/adblock/session_stats_factory.cc b/chrome/browser/adblock/session_stats_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/session_stats_factory.cc +@@ -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 . ++ */ ++ ++#include "chrome/browser/adblock/session_stats_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/content/browser/session_stats_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++SessionStats* SessionStatsFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++ ++// static ++SessionStatsFactory* SessionStatsFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++SessionStatsFactory::SessionStatsFactory() ++ : BrowserContextKeyedServiceFactory( ++ "SessionStats", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(ResourceClassificationRunnerFactory::GetInstance()); ++} ++ ++SessionStatsFactory::~SessionStatsFactory() = default; ++ ++KeyedService* SessionStatsFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new SessionStatsImpl( ++ ResourceClassificationRunnerFactory::GetForBrowserContext(context)); ++} ++ ++content::BrowserContext* SessionStatsFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/session_stats_factory.h b/chrome/browser/adblock/session_stats_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/session_stats_factory.h +@@ -0,0 +1,47 @@ ++/* ++ * 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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_SESSION_STATS_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_SESSION_STATS_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 SessionStats; ++class SessionStatsFactory : public BrowserContextKeyedServiceFactory { ++ public: ++ static SessionStats* GetForBrowserContext(content::BrowserContext* context); ++ static SessionStatsFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ SessionStatsFactory(); ++ ~SessionStatsFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_SESSION_STATS_FACTORY_H_ +diff --git a/chrome/browser/adblock/sitekey_storage_factory.cc b/chrome/browser/adblock/sitekey_storage_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/sitekey_storage_factory.cc +@@ -0,0 +1,59 @@ ++/* ++ * 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 . ++ */ ++ ++#include "chrome/browser/adblock/sitekey_storage_factory.h" ++ ++#include ++ ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/core/sitekey_storage_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++SitekeyStorage* SitekeyStorageFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++SitekeyStorageFactory* SitekeyStorageFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++SitekeyStorageFactory::SitekeyStorageFactory() ++ : BrowserContextKeyedServiceFactory( ++ "SitekeyStorage", ++ BrowserContextDependencyManager::GetInstance()) {} ++ ++SitekeyStorageFactory::~SitekeyStorageFactory() = default; ++ ++KeyedService* SitekeyStorageFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new SitekeyStorageImpl(); ++} ++ ++content::BrowserContext* SitekeyStorageFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/sitekey_storage_factory.h b/chrome/browser/adblock/sitekey_storage_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/sitekey_storage_factory.h +@@ -0,0 +1,47 @@ ++/* ++ * 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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_SITEKEY_STORAGE_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_SITEKEY_STORAGE_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 SitekeyStorage; ++class SitekeyStorageFactory : public BrowserContextKeyedServiceFactory { ++ public: ++ static SitekeyStorage* GetForBrowserContext(content::BrowserContext* context); ++ static SitekeyStorageFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ SitekeyStorageFactory(); ++ ~SitekeyStorageFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_SITEKEY_STORAGE_FACTORY_H_ +diff --git a/chrome/browser/adblock/subscription_persistent_metadata_factory.cc b/chrome/browser/adblock/subscription_persistent_metadata_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/subscription_persistent_metadata_factory.cc +@@ -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 . ++ */ ++ ++#include "chrome/browser/adblock/subscription_persistent_metadata_factory.h" ++ ++#include ++ ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/core/subscription/subscription_persistent_metadata_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++ ++// static ++SubscriptionPersistentMetadata* ++SubscriptionPersistentMetadataFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++SubscriptionPersistentMetadataFactory* ++SubscriptionPersistentMetadataFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++SubscriptionPersistentMetadataFactory::SubscriptionPersistentMetadataFactory() ++ : BrowserContextKeyedServiceFactory( ++ "AdblockSubscriptionPersistentMetadata", ++ BrowserContextDependencyManager::GetInstance()) {} ++SubscriptionPersistentMetadataFactory:: ++ ~SubscriptionPersistentMetadataFactory() = default; ++ ++KeyedService* SubscriptionPersistentMetadataFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new SubscriptionPersistentMetadataImpl( ++ Profile::FromBrowserContext(context)->GetPrefs()); ++} ++ ++content::BrowserContext* ++SubscriptionPersistentMetadataFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/subscription_persistent_metadata_factory.h b/chrome/browser/adblock/subscription_persistent_metadata_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/subscription_persistent_metadata_factory.h +@@ -0,0 +1,49 @@ ++/* ++ * 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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_PERSISTENT_METADATA_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_PERSISTENT_METADATA_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 SubscriptionPersistentMetadata; ++class SubscriptionPersistentMetadataFactory ++ : public BrowserContextKeyedServiceFactory { ++ public: ++ static SubscriptionPersistentMetadata* GetForBrowserContext( ++ content::BrowserContext* context); ++ static SubscriptionPersistentMetadataFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ SubscriptionPersistentMetadataFactory(); ++ ~SubscriptionPersistentMetadataFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_PERSISTENT_METADATA_FACTORY_H_ +diff --git a/chrome/browser/adblock/subscription_service_factory.cc b/chrome/browser/adblock/subscription_service_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/subscription_service_factory.cc +@@ -0,0 +1,146 @@ ++/* ++ * 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 . ++ */ ++ ++#include "chrome/browser/adblock/subscription_service_factory.h" ++ ++#include ++#include ++#include ++ ++#include "base/bind.h" ++#include "base/threading/sequenced_task_runner_handle.h" ++#include "base/trace_event/trace_event.h" ++#include "chrome/browser/adblock/subscription_persistent_metadata_factory.h" ++#include "chrome/browser/browser_process.h" ++#include "chrome/browser/net/system_network_context_manager.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.h" ++#include "components/adblock/core/common/adblock_constants.h" ++#include "components/adblock/core/converter/converter.h" ++#include "components/adblock/core/subscription/installed_subscription_impl.h" ++#include "components/adblock/core/subscription/ongoing_subscription_request_impl.h" ++#include "components/adblock/core/subscription/preloaded_subscription_provider_impl.h" ++#include "components/adblock/core/subscription/subscription_config.h" ++#include "components/adblock/core/subscription/subscription_downloader_impl.h" ++#include "components/adblock/core/subscription/subscription_persistent_storage_impl.h" ++#include "components/adblock/core/subscription/subscription_service_impl.h" ++#include "components/adblock/core/subscription/subscription_validator_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "components/prefs/pref_service.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++namespace { ++ ++constexpr net::BackoffEntry::Policy kRetryBackoffPolicy = { ++ 0, // Number of initial errors to ignore. ++ 5000, // Initial delay in ms. ++ 2.0, // Factor by which the waiting time will be multiplied. ++ 0.2, // Fuzzing percentage. ++ 60 * 60 * 1000, // Maximum delay in ms. ++ -1, // Never discard the entry. ++ false, // Use initial delay. ++}; ++ ++std::unique_ptr MakeOngoingSubscriptionRequest( ++ PrefService* prefs, ++ scoped_refptr url_loader_factory) { ++ return std::make_unique( ++ prefs, &kRetryBackoffPolicy, url_loader_factory); ++} ++ ++ConverterResult ConvertFileToFlatbuffer(const GURL& subscription_url, ++ const base::FilePath& path) { ++ TRACE_EVENT1("eyeo", "ConvertFileToFlatbuffer", "url", ++ subscription_url.spec()); ++ std::ifstream input_stream(path.AsUTF8Unsafe()); ++ if (!input_stream.is_open() || !input_stream.good()) { ++ ConverterResult result; ++ result.status = ConverterResult::Error; ++ return result; ++ } ++ return Converter().Convert( ++ input_stream, ++ {subscription_url, config::AllowPrivilegedFilters(subscription_url)}); ++} ++ ++scoped_refptr CustomFilterConverter( ++ const std::vector& filters) { ++ auto raw_data = Converter().Convert(filters, {CustomFiltersUrl(), true}); ++ return base::MakeRefCounted( ++ std::move(raw_data), Subscription::InstallationState::Installed, ++ base::Time()); ++} ++ ++} // namespace ++ ++// static ++SubscriptionService* SubscriptionServiceFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++SubscriptionServiceFactory* SubscriptionServiceFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++SubscriptionServiceFactory::SubscriptionServiceFactory() ++ : BrowserContextKeyedServiceFactory( ++ "AdblockSubscriptionService", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(SubscriptionPersistentMetadataFactory::GetInstance()); ++} ++SubscriptionServiceFactory::~SubscriptionServiceFactory() = default; ++ ++KeyedService* SubscriptionServiceFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ auto* prefs = Profile::FromBrowserContext(context)->GetPrefs(); ++ auto main_thread_task_runner = base::SequencedTaskRunnerHandle::Get(); ++ auto* persistent_metadata = ++ SubscriptionPersistentMetadataFactory::GetForBrowserContext(context); ++ scoped_refptr url_loader_factory = ++ g_browser_process && g_browser_process->system_network_context_manager() ++ ? g_browser_process->system_network_context_manager() ++ ->GetSharedURLLoaderFactory() ++ : nullptr; ++ ++ auto storage = std::make_unique( ++ context->GetPath().AppendASCII("adblock_subscriptions"), ++ base::MakeRefCounted( ++ prefs, CurrentSchemaVersion(), main_thread_task_runner), ++ persistent_metadata); ++ auto downloader = std::make_unique( ++ utils::GetAppInfo(), ++ base::BindRepeating(&MakeOngoingSubscriptionRequest, ++ Profile::FromBrowserContext(context)->GetPrefs(), ++ url_loader_factory), ++ base::BindRepeating(&ConvertFileToFlatbuffer), persistent_metadata); ++ ++ return new SubscriptionServiceImpl( ++ prefs, std::move(storage), std::move(downloader), ++ std::make_unique(prefs), ++ base::BindRepeating(&CustomFilterConverter), persistent_metadata); ++} ++ ++content::BrowserContext* SubscriptionServiceFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/subscription_service_factory.h b/chrome/browser/adblock/subscription_service_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/subscription_service_factory.h +@@ -0,0 +1,48 @@ ++/* ++ * 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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_SERVICE_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_SERVICE_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 SubscriptionService; ++class SubscriptionServiceFactory : public BrowserContextKeyedServiceFactory { ++ public: ++ static SubscriptionService* GetForBrowserContext( ++ content::BrowserContext* context); ++ static SubscriptionServiceFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ SubscriptionServiceFactory(); ++ ~SubscriptionServiceFactory() override; ++ ++ // BrowserContextKeyedServiceFactory: ++ KeyedService* BuildServiceInstanceFor( ++ content::BrowserContext* context) const override; ++ content::BrowserContext* GetBrowserContextToUse( ++ content::BrowserContext* context) const override; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_SERVICE_FACTORY_H_ +diff --git a/chrome/browser/adblock/subscription_updater_factory.cc b/chrome/browser/adblock/subscription_updater_factory.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/subscription_updater_factory.cc +@@ -0,0 +1,83 @@ ++/* ++ * 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 . ++ */ ++ ++#include "chrome/browser/adblock/subscription_updater_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/subscription_persistent_metadata_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/core/subscription/subscription_updater_impl.h" ++#include "components/keyed_service/content/browser_context_dependency_manager.h" ++#include "content/public/browser/browser_context.h" ++ ++namespace adblock { ++namespace { ++constexpr auto kInitialDelay = base::Seconds(30); ++constexpr auto kCheckInterval = base::Hours(1); ++} // namespace ++ ++// static ++SubscriptionUpdater* SubscriptionUpdaterFactory::GetForBrowserContext( ++ content::BrowserContext* context) { ++ return static_cast( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++SubscriptionUpdaterFactory* SubscriptionUpdaterFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++SubscriptionUpdaterFactory::SubscriptionUpdaterFactory() ++ : BrowserContextKeyedServiceFactory( ++ "AdblockSubscriptionUpdater", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(SubscriptionServiceFactory::GetInstance()); ++ DependsOn(SubscriptionPersistentMetadataFactory::GetInstance()); ++} ++SubscriptionUpdaterFactory::~SubscriptionUpdaterFactory() = default; ++ ++KeyedService* SubscriptionUpdaterFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ auto service = std::make_unique( ++ Profile::FromBrowserContext(context)->GetPrefs(), ++ SubscriptionServiceFactory::GetForBrowserContext(context), ++ SubscriptionPersistentMetadataFactory::GetForBrowserContext(context), ++ kInitialDelay, kCheckInterval); ++ service->StartSchedule(); ++ return service.release(); ++} ++ ++content::BrowserContext* SubscriptionUpdaterFactory::GetBrowserContextToUse( ++ content::BrowserContext* context) const { ++ return chrome::GetBrowserContextRedirectedInIncognito(context); ++} ++ ++bool SubscriptionUpdaterFactory::ServiceIsCreatedWithBrowserContext() const { ++ // Create the service ASAP via the factory framework to avoid patching ++ // chrome_browser_main.cc with pointless GetForBrowserContext() call. ++ return true; ++} ++ ++bool SubscriptionUpdaterFactory::ServiceIsNULLWhileTesting() const { ++ return true; ++} ++ ++} // namespace adblock +diff --git a/chrome/browser/adblock/subscription_updater_factory.h b/chrome/browser/adblock/subscription_updater_factory.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/adblock/subscription_updater_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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_UPDATER_FACTORY_H_ ++#define CHROME_BROWSER_ADBLOCK_SUBSCRIPTION_UPDATER_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 SubscriptionUpdater; ++class SubscriptionUpdaterFactory : public BrowserContextKeyedServiceFactory { ++ public: ++ static SubscriptionUpdater* GetForBrowserContext( ++ content::BrowserContext* context); ++ static SubscriptionUpdaterFactory* GetInstance(); ++ ++ private: ++ friend class base::NoDestructor; ++ SubscriptionUpdaterFactory(); ++ ~SubscriptionUpdaterFactory() 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_ADBLOCK_SUBSCRIPTION_UPDATER_FACTORY_H_ +diff --git a/chrome/browser/android/adblock/adblock_jni.cc b/chrome/browser/android/adblock/adblock_jni.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/adblock_jni.cc +@@ -0,0 +1,568 @@ ++/* ++ * 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 . ++ */ ++#include "chrome/browser/android/adblock/adblock_jni.h" ++ ++#include ++#include ++#include ++ ++#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/command_line.h" ++#include "base/logging.h" ++#include "base/version.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/android/adblock/adblock_jni_factory.h" ++#include "chrome/browser/android/tab_android.h" ++#include "chrome/browser/browser_process.h" ++#include "chrome/browser/profiles/profile_manager.h" ++#include "components/adblock/android/jni_headers/AdblockComposeFilterSuggestionsCallback_jni.h" ++#include "components/adblock/android/jni_headers/AdblockController_jni.h" ++#include "components/adblock/android/jni_headers/AdblockElement_jni.h" ++#include "components/adblock/core/adblock_switches.h" ++#include "components/adblock/core/common/adblock_utils.h" ++#include "components/prefs/pref_service.h" ++#include "content/public/browser/browser_thread.h" ++#include "content/public/browser/render_frame_host.h" ++#include "content/public/browser/render_process_host.h" ++#include "content/public/browser/web_contents.h" ++ ++using base::android::AttachCurrentThread; ++using base::android::ConvertJavaStringToUTF8; ++using base::android::ConvertUTF8ToJavaString; ++using base::android::JavaParamRef; ++using base::android::JavaRef; ++using base::android::ScopedJavaGlobalRef; ++using base::android::ScopedJavaLocalRef; ++using base::android::ToJavaArrayOfStrings; ++ ++namespace adblock { ++ ++namespace { ++ ++AdblockController* GetController() { ++ if (!g_browser_process || !g_browser_process->profile_manager()) ++ return nullptr; ++ return AdblockControllerFactory::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()); ++} ++ ++absl::optional FindRecommendedSubscription( ++ const base::android::JavaParamRef& subscription) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ DCHECK(adblock::GetController()); ++ ++ GURL url(ConvertJavaStringToUTF8(subscription)); ++ auto recommended = adblock::GetController()->GetKnownSubscriptions(); ++ auto item = std::find_if(recommended.begin(), recommended.end(), ++ [&url](const KnownSubscriptionInfo& subscription) { ++ return subscription.url == url; ++ }); ++ ++ if (item == recommended.end()) { ++ return {}; ++ } ++ ++ return *item; ++} ++ ++// TODO(mpawlowski): this is currently useless, see DPD-699 ++class JavaElement { ++ public: ++ JavaElement(JNIEnv* environment, const ScopedJavaGlobalRef& object) ++ : obj_(object) {} ++ ++ ~JavaElement() {} ++ ++ std::string GetLocalName() const { ++ JNIEnv* env = AttachCurrentThread(); ++ auto name = Java_AdblockElement_getLocalName(env, obj_); ++ return name.is_null() ? "" : ConvertJavaStringToUTF8(name); ++ } ++ ++ std::string GetDocumentLocation() const { ++ JNIEnv* env = AttachCurrentThread(); ++ auto location = Java_AdblockElement_getDocumentLocation(env, obj_); ++ return location.is_null() ? "" : ConvertJavaStringToUTF8(location); ++ } ++ ++ std::string GetAttribute(const std::string& name) const { ++ JNIEnv* env = AttachCurrentThread(); ++ auto attr = Java_AdblockElement_getAttribute( ++ env, obj_, ConvertUTF8ToJavaString(env, name)); ++ ++ return attr.is_null() ? "" : ConvertJavaStringToUTF8(attr); ++ } ++ ++ std::vector GetChildren() const { ++ std::vector res; ++ ++ if (children_.empty()) { ++ JNIEnv* env = AttachCurrentThread(); ++ auto array = Java_AdblockElement_getChildren(env, obj_); ++ ++ if (!array.is_null()) { ++ jsize array_length = env->GetArrayLength(array.obj()); ++ children_.reserve(array_length); ++ ++ for (jsize n = 0; n != array_length; ++n) { ++ children_.push_back(JavaElement( ++ env, ScopedJavaGlobalRef( ++ env, env->GetObjectArrayElement(array.obj(), n)))); ++ } ++ } ++ } ++ ++ res.reserve(children_.size()); ++ std::transform(children_.begin(), children_.end(), std::back_inserter(res), ++ [](const auto& cur) { return &cur; }); ++ ++ return res; ++ } ++ ++ private: ++ ScopedJavaGlobalRef obj_; ++ mutable std::vector children_; ++}; ++ ++void ComposeFilterSuggestionsResult( ++ const base::android::ScopedJavaGlobalRef& element, ++ const base::android::ScopedJavaGlobalRef& callback, ++ const std::vector& filters) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ JNIEnv* env = AttachCurrentThread(); ++ auto j_filters = ToJavaArrayOfStrings(env, filters); ++ Java_AdblockComposeFilterSuggestionsCallback_onDone(env, callback, element, ++ j_filters); ++} ++ ++constexpr int kNoId = -1; ++ ++int GetTabId(content::RenderFrameHost* render_frame_host) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ ++ auto* web_contents = ++ content::WebContents::FromRenderFrameHost(render_frame_host); ++ if (!web_contents) ++ return kNoId; ++ ++ auto* tab = TabAndroid::FromWebContents(web_contents); ++ if (!tab) ++ return kNoId; ++ ++ return tab->GetAndroidId(); ++} ++ ++std::vector SubscriptionsToUrls( ++ const std::vector>& subscriptions) { ++ std::vector urls; ++ urls.reserve(subscriptions.size()); ++ base::ranges::transform( ++ subscriptions, std::back_inserter(urls), ++ [](const auto& sub) { return sub->GetSourceUrl().spec(); }); ++ return urls; ++} ++ ++} // namespace ++ ++AdblockJNI::AdblockJNI(ResourceClassificationRunner* classification_runner, ++ AdblockController* controller) ++ : classification_runner_(classification_runner), controller_(controller) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ if (classification_runner_) // Might not be there in unit tests. ++ classification_runner_->AddObserver(this); ++ if (controller_) ++ controller_->AddObserver(this); ++} ++ ++AdblockJNI::~AdblockJNI() { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ if (controller_) ++ controller_->RemoveObserver(this); ++ if (classification_runner_) ++ classification_runner_->RemoveObserver(this); ++} ++ ++void AdblockJNI::Bind(JavaObjectWeakGlobalRef weak_java_controller) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ weak_java_controller_ = weak_java_controller; ++} ++ ++void AdblockJNI::OnAdMatched(const GURL& url, ++ mojom::FilterMatchResult result, ++ const std::vector& parent_frame_urls, ++ ContentType content_type, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ DCHECK(render_frame_host); ++ DCHECK(result == mojom::FilterMatchResult::kBlockRule || ++ result == mojom::FilterMatchResult::kAllowRule); ++ if (!has_counters_observers_) ++ return; ++ const bool was_blocked = result == mojom::FilterMatchResult::kBlockRule; ++ DVLOG(3) << "[eyeo] Ad matched " << url << "(type: " << content_type ++ << (was_blocked ? ", blocked" : ", allowed") << ")"; ++ JNIEnv* env = AttachCurrentThread(); ++ ++ ScopedJavaLocalRef obj = weak_java_controller_.get(env); ++ if (obj.is_null()) ++ return; ++ ++ ScopedJavaLocalRef j_url = ConvertUTF8ToJavaString(env, url.spec()); ++ ScopedJavaLocalRef j_parents = ++ ToJavaArrayOfStrings(env, adblock::utils::ConvertURLs(parent_frame_urls)); ++ ScopedJavaLocalRef j_subscription = ++ ConvertUTF8ToJavaString(env, subscription.spec()); ++ int tab_id = GetTabId(render_frame_host); ++ Java_AdblockController_adMatchedCallback( ++ env, obj, j_url, was_blocked, j_parents, j_subscription, ++ static_cast(content_type), tab_id); ++} ++ ++void AdblockJNI::OnPageAllowed(const GURL& url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ DCHECK(render_frame_host); ++ if (!has_counters_observers_) ++ return; ++ DVLOG(3) << "[eyeo] Page allowed " << url; ++ JNIEnv* env = AttachCurrentThread(); ++ ++ ScopedJavaLocalRef obj = weak_java_controller_.get(env); ++ if (obj.is_null()) ++ return; ++ ++ ScopedJavaLocalRef j_url = ConvertUTF8ToJavaString(env, url.spec()); ++ ScopedJavaLocalRef j_subscription = ++ ConvertUTF8ToJavaString(env, subscription.spec()); ++ int tab_id = GetTabId(render_frame_host); ++ Java_AdblockController_pageAllowedCallback(env, obj, j_url, j_subscription, ++ tab_id); ++} ++ ++void AdblockJNI::OnPopupMatched(const GURL& url, ++ mojom::FilterMatchResult result, ++ const GURL& opener_url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ DCHECK(render_frame_host); ++ DCHECK(result == mojom::FilterMatchResult::kBlockRule || ++ result == mojom::FilterMatchResult::kAllowRule); ++ if (!has_counters_observers_) ++ return; ++ const bool was_blocked = result == mojom::FilterMatchResult::kBlockRule; ++ DVLOG(3) << "[eyeo] Popup matched " << url ++ << (was_blocked ? ", blocked" : ", allowed"); ++ JNIEnv* env = AttachCurrentThread(); ++ ++ ScopedJavaLocalRef obj = weak_java_controller_.get(env); ++ if (obj.is_null()) ++ return; ++ ++ ScopedJavaLocalRef j_url = ConvertUTF8ToJavaString(env, url.spec()); ++ ScopedJavaLocalRef j_opener = ++ ConvertUTF8ToJavaString(env, opener_url.spec()); ++ ScopedJavaLocalRef j_subscription = ++ ConvertUTF8ToJavaString(env, subscription.spec()); ++ int tab_id = GetTabId(render_frame_host); ++ Java_AdblockController_popupMatchedCallback(env, obj, j_url, was_blocked, ++ j_opener, j_subscription, tab_id); ++} ++ ++void AdblockJNI::SetHasAdblockCountersObservers(bool has_observers) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ has_counters_observers_ = has_observers; ++} ++ ++void AdblockJNI::OnSubscriptionUpdated(const GURL& url) { ++ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ++ JNIEnv* env = AttachCurrentThread(); ++ ScopedJavaLocalRef obj = weak_java_controller_.get(env); ++ if (obj.is_null()) ++ return; ++ ++ ScopedJavaLocalRef j_url = ConvertUTF8ToJavaString(env, url.spec()); ++ Java_AdblockController_subscriptionUpdatedCallback(env, obj, j_url); ++} ++ ++} // namespace adblock ++ ++static void JNI_AdblockController_SetHasAdblockCountersObservers( ++ JNIEnv* env, ++ const base::android::JavaParamRef& jcaller, ++ jboolean has_observers) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return; ++ adblock::GetJNI()->SetHasAdblockCountersObservers(has_observers == JNI_TRUE); ++} ++ ++static void JNI_AdblockController_Bind( ++ JNIEnv* env, ++ const base::android::JavaParamRef& caller) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return; ++ JavaObjectWeakGlobalRef weak_controller_ref(env, caller); ++ adblock::GetJNI()->Bind(weak_controller_ref); ++} ++ ++static jboolean JNI_AdblockController_IsAdblockEnabled(JNIEnv* env) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ DCHECK(adblock::GetController()); ++ return adblock::GetController()->IsAdblockEnabled() ? JNI_TRUE : JNI_FALSE; ++} ++ ++static jboolean JNI_AdblockController_IsAcceptableAdsEnabled(JNIEnv* env) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ DCHECK(adblock::GetController()); ++ return adblock::GetController()->IsAcceptableAdsEnabled() ? JNI_TRUE ++ : JNI_FALSE; ++} ++ ++static void JNI_AdblockController_SetAdblockEnabled(JNIEnv* env, ++ jboolean j_aa_enabled) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ DCHECK(adblock::GetController()); ++ return adblock::GetController()->SetAdblockEnabled(j_aa_enabled == JNI_TRUE); ++} ++ ++static void JNI_AdblockController_SetAcceptableAdsEnabled( ++ JNIEnv* env, ++ jboolean j_aa_enabled) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ DCHECK(adblock::GetController()); ++ return adblock::GetController()->SetAcceptableAdsEnabled(j_aa_enabled == ++ JNI_TRUE); ++} ++ ++static void JNI_AdblockController_SelectSubscription( ++ JNIEnv* env, ++ const base::android::JavaParamRef& url) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return; ++ adblock::GetController()->SelectBuiltInSubscription( ++ GURL{ConvertJavaStringToUTF8(url)}); ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_AdblockController_GetSelectedSubscriptions(JNIEnv* env) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return ToJavaArrayOfStrings(env, std::vector{}); ++ ++ return ToJavaArrayOfStrings( ++ env, adblock::SubscriptionsToUrls( ++ adblock::GetController()->GetSelectedBuiltInSubscriptions())); ++} ++ ++static void JNI_AdblockController_UnselectSubscription( ++ JNIEnv* env, ++ const base::android::JavaParamRef& url) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return; ++ ++ adblock::GetController()->UnselectBuiltInSubscription( ++ GURL{ConvertJavaStringToUTF8(url)}); ++} ++ ++static void JNI_AdblockController_AddCustomSubscription( ++ JNIEnv* env, ++ const base::android::JavaParamRef& url) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return; ++ adblock::GetController()->AddCustomSubscription( ++ GURL{ConvertJavaStringToUTF8(url)}); ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_AdblockController_GetCustomSubscriptions(JNIEnv* env) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return ToJavaArrayOfStrings(env, std::vector{}); ++ ++ return ToJavaArrayOfStrings( ++ env, adblock::SubscriptionsToUrls( ++ adblock::GetController()->GetCustomSubscriptions())); ++} ++ ++static void JNI_AdblockController_RemoveCustomSubscription( ++ JNIEnv* env, ++ const base::android::JavaParamRef& url) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return; ++ adblock::GetController()->RemoveCustomSubscription( ++ GURL{ConvertJavaStringToUTF8(url)}); ++} ++ ++static void JNI_AdblockController_AddAllowedDomain( ++ JNIEnv* env, ++ const base::android::JavaParamRef& domain) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return; ++ adblock::GetController()->AddAllowedDomain(ConvertJavaStringToUTF8(domain)); ++} ++ ++static void JNI_AdblockController_RemoveAllowedDomain( ++ JNIEnv* env, ++ const base::android::JavaParamRef& domain) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return; ++ adblock::GetController()->RemoveAllowedDomain( ++ ConvertJavaStringToUTF8(domain)); ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_AdblockController_GetAllowedDomains(JNIEnv* env) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return ToJavaArrayOfStrings(env, std::vector{}); ++ ++ return ToJavaArrayOfStrings(env, ++ adblock::GetController()->GetAllowedDomains()); ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_AdblockController_GetRecommendedSubscriptions(JNIEnv* env) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ if (!adblock::GetController()) ++ return ToJavaArrayOfStrings(env, std::vector{}); ++ ++ auto list = adblock::GetController()->GetKnownSubscriptions(); ++ std::vector recommended; ++ for (const auto& element : list) { ++ if (element.ui_visibility == adblock::SubscriptionUiVisibility::Visible) ++ recommended.emplace_back(element.url.spec()); ++ } ++ return ToJavaArrayOfStrings(env, recommended); ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_AdblockController_GetRecommendedSubscriptionTitle( ++ JNIEnv* env, ++ const base::android::JavaParamRef& subscription) { ++ if (!adblock::GetController()) ++ return ConvertUTF8ToJavaString(env, {}); ++ auto item = adblock::FindRecommendedSubscription(subscription); ++ std::string title; ++ if (item) { ++ title = item->title; ++ } ++ ++ ScopedJavaLocalRef j_title = ConvertUTF8ToJavaString(env, title); ++ return j_title; ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_AdblockController_GetRecommendedSubscriptionLanguages( ++ JNIEnv* env, ++ const base::android::JavaParamRef& subscription) { ++ if (!adblock::GetController()) ++ return ConvertUTF8ToJavaString(env, {}); ++ auto item = adblock::FindRecommendedSubscription(subscription); ++ std::string languages_str; ++ if (item) { ++ languages_str = adblock::utils::SerializeLanguages(item->languages); ++ } ++ ScopedJavaLocalRef j_languages = ++ ConvertUTF8ToJavaString(env, languages_str); ++ return j_languages; ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_AdblockController_GetSelectedSubscriptionVersion( ++ JNIEnv* env, ++ const base::android::JavaParamRef& subscription) { ++ const GURL url(ConvertJavaStringToUTF8(subscription)); ++ const auto built_in_subscriptions = ++ adblock::GetController()->GetSelectedBuiltInSubscriptions(); ++ auto it = base::ranges::find(built_in_subscriptions, url, ++ &adblock::Subscription::GetSourceUrl); ++ if (it == built_in_subscriptions.end()) { ++ const auto custom_subscriptions = ++ adblock::GetController()->GetCustomSubscriptions(); ++ it = base::ranges::find(custom_subscriptions, url, ++ &adblock::Subscription::GetSourceUrl); ++ if (it == custom_subscriptions.end()) ++ return ConvertUTF8ToJavaString(env, {}); ++ } ++ ScopedJavaLocalRef j_version = ++ ConvertUTF8ToJavaString(env, (*it)->GetCurrentVersion()); ++ return j_version; ++} ++ ++static void JNI_AdblockController_ComposeFilterSuggestions( ++ JNIEnv* env, ++ const base::android::JavaParamRef& element, ++ const base::android::JavaParamRef& callback) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ // TODO implement ComposeFilterSuggestions in flatbuffer core: DPD-699 ++ // This is currently not doing the right thing. ++ base::android::ScopedJavaGlobalRef element_ref(element); ++ base::android::ScopedJavaGlobalRef callback_ref(callback); ++ adblock::ComposeFilterSuggestionsResult(element_ref, callback_ref, {}); ++} ++ ++static void JNI_AdblockController_AddCustomFilter( ++ JNIEnv* env, ++ const base::android::JavaParamRef& filter) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ auto* controller = adblock::GetController(); ++ if (!controller) ++ return; ++ ++ controller->AddCustomFilter(ConvertJavaStringToUTF8(filter)); ++} ++ ++static void JNI_AdblockController_RemoveCustomFilter( ++ JNIEnv* env, ++ const base::android::JavaParamRef& filter) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ auto* controller = adblock::GetController(); ++ if (!controller) ++ return; ++ ++ controller->RemoveCustomFilter(ConvertJavaStringToUTF8(filter)); ++} ++ ++static base::android::ScopedJavaLocalRef ++JNI_AdblockController_GetCustomFilters(JNIEnv* env) { ++ DCHECK_CURRENTLY_ON(content::BrowserThread::UI); ++ auto* controller = adblock::GetController(); ++ if (!controller) ++ return ToJavaArrayOfStrings(env, std::vector{}); ++ ++ return ToJavaArrayOfStrings(env, controller->GetCustomFilters()); ++} +diff --git a/chrome/browser/android/adblock/adblock_jni.h b/chrome/browser/android/adblock/adblock_jni.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/android/adblock/adblock_jni.h +@@ -0,0 +1,74 @@ ++/* ++ * 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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_H_ ++#define CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_H_ ++ ++#include ++ ++#include "base/android/jni_weak_ref.h" ++#include "components/adblock/content/browser/resource_classification_runner.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/keyed_service/core/keyed_service.h" ++ ++namespace content { ++class BrowserContext; ++} ++ ++namespace adblock { ++ ++class AdblockJNI : public ResourceClassificationRunner::Observer, ++ public AdblockController::Observer, ++ public KeyedService { ++ public: ++ AdblockJNI(ResourceClassificationRunner* classification_runner, ++ AdblockController* controller); ++ ~AdblockJNI() override; ++ ++ void Bind(JavaObjectWeakGlobalRef weak_java_controller); ++ void SetHasAdblockCountersObservers(bool has_observers); ++ ++ // ResourceClassificationRunner::Observer: ++ void OnAdMatched(const GURL& url, ++ mojom::FilterMatchResult result, ++ const std::vector& parent_frame_urls, ++ ContentType content_type, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription) override; ++ void OnPageAllowed(const GURL& url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription) final; ++ void OnPopupMatched(const GURL& url, ++ mojom::FilterMatchResult match_result, ++ const GURL& opener_url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription) override; ++ ++ // AdblockController::Observer: ++ void OnSubscriptionUpdated(const GURL& url) override; ++ ++ private: ++ SEQUENCE_CHECKER(sequence_checker_); ++ ResourceClassificationRunner* classification_runner_; ++ AdblockController* controller_; ++ bool has_counters_observers_{false}; ++ JavaObjectWeakGlobalRef weak_java_controller_; ++}; ++ ++} // namespace adblock ++ ++#endif // CHROME_BROWSER_ANDROID_ADBLOCK_ADBLOCK_JNI_H_ +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,75 @@ ++/* ++ * 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 . ++ */ ++ ++#include "chrome/browser/android/adblock/adblock_jni_factory.h" ++ ++#include ++ ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/android/adblock/adblock_jni.h" ++#include "chrome/browser/profiles/incognito_helpers.h" ++#include "chrome/browser/profiles/profile.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( ++ GetInstance()->GetServiceForBrowserContext(context, true)); ++} ++// static ++AdblockJNIFactory* AdblockJNIFactory::GetInstance() { ++ static base::NoDestructor instance; ++ return instance.get(); ++} ++ ++AdblockJNIFactory::AdblockJNIFactory() ++ : BrowserContextKeyedServiceFactory( ++ "AdblockJNI", ++ BrowserContextDependencyManager::GetInstance()) { ++ DependsOn(AdblockControllerFactory::GetInstance()); ++ DependsOn(ResourceClassificationRunnerFactory::GetInstance()); ++} ++ ++AdblockJNIFactory::~AdblockJNIFactory() = default; ++ ++KeyedService* AdblockJNIFactory::BuildServiceInstanceFor( ++ content::BrowserContext* context) const { ++ return new AdblockJNI( ++ ResourceClassificationRunnerFactory::GetForBrowserContext(context), ++ AdblockControllerFactory::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 . ++ */ ++ ++#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_JNI_FACTORY_H_ ++#define CHROME_BROWSER_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() 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_ADBLOCK_ADBLOCK_JNI_FACTORY_H_ +diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc ++++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +@@ -1,6 +1,10 @@ + // Copyright 2014 The Chromium Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. ++// ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. + + #include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h" + +@@ -102,6 +106,7 @@ const char* const kChromeSettingsSubPages[] = { + chrome::kImportDataSubPage, chrome::kManageProfileSubPage, + chrome::kPeopleSubPage, + #endif ++ chrome::kAdblockSubPage, + }; + #endif // BUILDFLAG(IS_ANDROID) + +diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc +--- a/chrome/browser/client_hints/client_hints_browsertest.cc ++++ b/chrome/browser/client_hints/client_hints_browsertest.cc +@@ -1,6 +1,10 @@ + // Copyright 2017 The Chromium Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. ++// ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. + + #include + #include +@@ -509,8 +513,12 @@ class ClientHintsBrowserTest : public policy::PolicyTest { + std::unique_ptr feature_list(new base::FeatureList); + feature_list->InitializeFromCommandLine( + "UserAgentClientHint,CriticalClientHint," +- "AcceptCHFrame,PrefersColorSchemeClientHintHeader", +- ""); ++ "AcceptCHFrame,PrefersColorSchemeClientHintHeader," ++ "", ++ // Disabling AdblockPlus because the async implementation of ++ // AdblockURLLoaderThrottle::WillStartRequest confuses ++ // ThirdPartyURLLoaderInterceptor. ++ "AdblockPlus"); + return feature_list; + } + +diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn +--- a/chrome/browser/extensions/BUILD.gn ++++ b/chrome/browser/extensions/BUILD.gn +@@ -1,6 +1,10 @@ + # Copyright 2014 The Chromium Authors. All rights reserved. + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. ++# ++# This source code is a part of eyeo Chromium SDK. ++# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file. ++ + + import("//build/config/chromebox_for_meetings/buildflags.gni") + import("//build/config/chromeos/ui_mode.gni") +@@ -43,6 +47,8 @@ static_library("extensions") { + "activity_log/fullstream_ui_policy.h", + "api/activity_log_private/activity_log_private_api.cc", + "api/activity_log_private/activity_log_private_api.h", ++ "api/adblock_private/adblock_private_api.cc", ++ "api/adblock_private/adblock_private_api.h", + "api/autofill_private/autofill_private_api.cc", + "api/autofill_private/autofill_private_api.h", + "api/autofill_private/autofill_private_event_router.cc", +@@ -795,6 +801,7 @@ static_library("extensions") { + "//chrome/browser/safe_browsing:metrics_collector", + "//chrome/browser/ui/tabs:tab_enums", + "//chrome/browser/web_applications", ++ "//components/adblock/content:browser", + "//components/cbor:cbor", + "//components/device_reauth", + "//components/safe_browsing/content/browser", +diff --git a/chrome/browser/extensions/api/BUILD.gn b/chrome/browser/extensions/api/BUILD.gn +--- a/chrome/browser/extensions/api/BUILD.gn ++++ b/chrome/browser/extensions/api/BUILD.gn +@@ -1,6 +1,10 @@ + # Copyright 2018 The Chromium Authors. All rights reserved. + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. ++# ++# This source code is a part of eyeo Chromium SDK. ++# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file. ++ + + import("//chrome/common/extensions/api/api_sources.gni") + import("//chrome/common/features.gni") +@@ -41,6 +45,7 @@ function_registration("api_registration") { + # include generated headers from these targets. + # TODO(brettw) this should be made unnecessary if possible. + "//chrome/common/extensions/api", ++ "//components/adblock/content:browser", + "//components/sync", + "//skia", + "//third_party/metrics_proto", +diff --git a/chrome/browser/extensions/api/adblock_private/adblock_private_api.cc b/chrome/browser/extensions/api/adblock_private/adblock_private_api.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/extensions/api/adblock_private/adblock_private_api.cc +@@ -0,0 +1,705 @@ ++// 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 . ++ ++#include "chrome/browser/extensions/api/adblock_private/adblock_private_api.h" ++ ++#include "base/containers/flat_map.h" ++#include "base/no_destructor.h" ++#include "base/time/time_to_iso8601.h" ++#include "base/values.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/adblock/session_stats_factory.h" ++#include "chrome/browser/extensions/extension_tab_util.h" ++#include "chrome/common/extensions/api/tabs.h" ++#include "components/adblock/content/browser/resource_classification_runner.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/common/adblock_utils.h" ++#include "components/adblock/core/common/allowed_connection_type.h" ++#include "components/adblock/core/common/content_type.h" ++#include "components/adblock/core/session_stats.h" ++#include "components/sessions/core/session_id.h" ++#include "content/public/browser/web_contents.h" ++#include "url/gurl.h" ++ ++namespace extensions { ++ ++namespace { ++ ++enum class BuiltInSubscriptionAction { kSelect, kUnselect }; ++ ++std::string RunBuiltInSubscriptionAction( ++ BuiltInSubscriptionAction action, ++ content::BrowserContext* browser_context, ++ const GURL& url) { ++ if (!url.is_valid()) ++ return "Invalid URL"; ++ auto* controller = ++ adblock::AdblockControllerFactory::GetForBrowserContext(browser_context); ++ auto recommended = controller->GetKnownSubscriptions(); ++ if (!recommended.empty()) { ++ auto item = ++ std::find_if(recommended.begin(), recommended.end(), ++ [&url](const adblock::KnownSubscriptionInfo& recommended) { ++ return recommended.url == url; ++ }); ++ if (item == recommended.end()) ++ return "Not a built-in subscription"; ++ } ++ ++ switch (action) { ++ case BuiltInSubscriptionAction::kSelect: ++ controller->SelectBuiltInSubscription(url); ++ break; ++ case BuiltInSubscriptionAction::kUnselect: ++ controller->UnselectBuiltInSubscription(url); ++ break; ++ default: ++ NOTREACHED(); ++ } ++ ++ return {}; ++} ++ ++enum class CustomSubscriptionAction { kAdd, kRemove }; ++ ++std::string RunCustomSubscriptionAction( ++ CustomSubscriptionAction action, ++ content::BrowserContext* browser_context, ++ const GURL& url) { ++ if (!url.is_valid()) ++ return "Invalid URL"; ++ auto* controller = ++ adblock::AdblockControllerFactory::GetForBrowserContext(browser_context); ++ switch (action) { ++ case CustomSubscriptionAction::kAdd: ++ controller->AddCustomSubscription(url); ++ break; ++ case CustomSubscriptionAction::kRemove: ++ controller->RemoveCustomSubscription(url); ++ break; ++ default: ++ NOTREACHED(); ++ } ++ ++ return {}; ++} ++ ++std::vector CopySessionsStats( ++ const std::map& source) { ++ std::vector result; ++ for (auto& entry : source) { ++ api::adblock_private::SessionStatsEntry js_entry; ++ js_entry.url = entry.first.spec(); ++ js_entry.count = entry.second; ++ result.emplace_back(std::move(js_entry)); ++ } ++ return result; ++} ++ ++std::string SubscriptionInstallationStateToString( ++ adblock::Subscription::InstallationState state) { ++ using State = adblock::Subscription::InstallationState; ++ switch (state) { ++ case State::Installed: ++ return "Installed"; ++ case State::Installing: ++ return "Installing"; ++ case State::Preloaded: ++ return "Preloaded"; ++ } ++ NOTREACHED(); ++ return ""; ++} ++ ++std::vector CopySubscriptions( ++ const std::vector> ++ current_subscriptions) { ++ std::vector result; ++ for (auto& sub : current_subscriptions) { ++ api::adblock_private::Subscription js_sub; ++ js_sub.url = sub->GetSourceUrl().spec(); ++ js_sub.title = sub->GetTitle(); ++ js_sub.current_version = sub->GetCurrentVersion(); ++ js_sub.installation_state = ++ SubscriptionInstallationStateToString(sub->GetInstallationState()); ++ js_sub.last_installation_time = ++ base::TimeToISO8601(sub->GetInstallationTime()); ++ result.emplace_back(std::move(js_sub)); ++ } ++ return result; ++} ++ ++} // namespace ++ ++template <> ++void BrowserContextKeyedAPIFactory< ++ AdblockPrivateAPI>::DeclareFactoryDependencies() { ++ DependsOn(adblock::AdblockControllerFactory::GetInstance()); ++ DependsOn(adblock::ResourceClassificationRunnerFactory::GetInstance()); ++ DependsOn(adblock::SessionStatsFactory::GetInstance()); ++} ++ ++// static ++BrowserContextKeyedAPIFactory* ++AdblockPrivateAPI::GetFactoryInstance() { ++ static base::NoDestructor> ++ instance; ++ return instance.get(); ++} ++ ++class AdblockPrivateAPI::AdblockAPIEventRouter ++ : public adblock::ResourceClassificationRunner::Observer, ++ public adblock::AdblockController::Observer { ++ public: ++ explicit AdblockAPIEventRouter(content::BrowserContext* context) ++ : context_(context) { ++ adblock::ResourceClassificationRunnerFactory::GetForBrowserContext(context) ++ ->AddObserver(this); ++ adblock::AdblockControllerFactory::GetForBrowserContext(context) ++ ->AddObserver(this); ++ } ++ ++ ~AdblockAPIEventRouter() override { ++ adblock::ResourceClassificationRunnerFactory::GetForBrowserContext(context_) ++ ->RemoveObserver(this); ++ adblock::AdblockControllerFactory::GetForBrowserContext(context_) ++ ->RemoveObserver(this); ++ } ++ ++ // adblock::ResourceClassificationRunner::Observer: ++ void OnAdMatched(const GURL& url, ++ adblock::mojom::FilterMatchResult match_result, ++ const std::vector& parent_frame_urls, ++ adblock::ContentType content_type, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription) override { ++ std::unique_ptr event; ++ api::adblock_private::AdInfo info = ++ CreateAdInfoObject(url, subscription, render_frame_host); ++ info.parent_frame_urls = adblock::utils::ConvertURLs(parent_frame_urls); ++ info.content_type = adblock::ContentTypeToString(content_type); ++ ++ if (match_result == adblock::mojom::FilterMatchResult::kBlockRule) { ++ event = std::make_unique( ++ events::ADBLOCK_PRIVATE_AD_BLOCKED, ++ api::adblock_private::OnAdBlocked::kEventName, ++ api::adblock_private::OnAdBlocked::Create(info), context_); ++ } else { ++ DCHECK(match_result == adblock::mojom::FilterMatchResult::kAllowRule); ++ event = std::make_unique( ++ events::ADBLOCK_PRIVATE_AD_ALLOWED, ++ api::adblock_private::OnAdAllowed::kEventName, ++ api::adblock_private::OnAdAllowed::Create(info), context_); ++ } ++ ++ extensions::EventRouter::Get(context_)->BroadcastEvent(std::move(event)); ++ } ++ ++ void OnPageAllowed(const GURL& url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription) override { ++ api::adblock_private::AdInfo info = ++ CreateAdInfoObject(url, subscription, render_frame_host); ++ info.parent_frame_urls = std::vector{}; ++ info.content_type = ""; ++ ++ std::unique_ptr event = std::make_unique( ++ events::ADBLOCK_PRIVATE_PAGE_ALLOWED, ++ api::adblock_private::OnPageAllowed::kEventName, ++ api::adblock_private::OnPageAllowed::Create(info), context_); ++ ++ extensions::EventRouter::Get(context_)->BroadcastEvent(std::move(event)); ++ } ++ ++ void OnPopupMatched(const GURL& url, ++ adblock::mojom::FilterMatchResult match_result, ++ const GURL& opener_url, ++ content::RenderFrameHost* render_frame_host, ++ const GURL& subscription) override { ++ std::unique_ptr event; ++ api::adblock_private::AdInfo info = ++ CreateAdInfoObject(url, subscription, render_frame_host); ++ info.parent_frame_urls = std::vector{opener_url.spec()}; ++ info.content_type = ""; ++ ++ if (match_result == adblock::mojom::FilterMatchResult::kBlockRule) { ++ event = std::make_unique( ++ events::ADBLOCK_PRIVATE_POPUP_BLOCKED, ++ api::adblock_private::OnPopupBlocked::kEventName, ++ api::adblock_private::OnPopupBlocked::Create(info), context_); ++ } else { ++ DCHECK(match_result == adblock::mojom::FilterMatchResult::kAllowRule); ++ event = std::make_unique( ++ events::ADBLOCK_PRIVATE_POPUP_ALLOWED, ++ api::adblock_private::OnPopupAllowed::kEventName, ++ api::adblock_private::OnPopupAllowed::Create(info), context_); ++ } ++ ++ extensions::EventRouter::Get(context_)->BroadcastEvent(std::move(event)); ++ } ++ ++ // adblock::AdblockController::Observer: ++ void OnSubscriptionUpdated(const GURL& url) override { ++ std::unique_ptr event = std::make_unique( ++ events::ADBLOCK_PRIVATE_SUBSCRIPTION_UPDATED, ++ api::adblock_private::OnSubscriptionUpdated::kEventName, ++ api::adblock_private::OnSubscriptionUpdated::Create(url.spec()), ++ context_); ++ extensions::EventRouter::Get(context_)->BroadcastEvent(std::move(event)); ++ } ++ ++ private: ++ api::adblock_private::AdInfo CreateAdInfoObject( ++ const GURL& url, ++ const GURL& subscription, ++ content::RenderFrameHost* render_frame_host) { ++ DCHECK(render_frame_host); ++ api::adblock_private::AdInfo info; ++ info.url = url.spec(); ++ info.subscription = subscription.spec(); ++ info.tab_id = api::tabs::TAB_ID_NONE; ++ info.window_id = SessionID::InvalidValue().id(); ++ const content::WebContents* wc = ++ content::WebContents::FromRenderFrameHost(render_frame_host); ++ if (wc) { ++ info.tab_id = ExtensionTabUtil::GetTabId(wc); ++ info.window_id = ExtensionTabUtil::GetWindowIdOfTab(wc); ++ } ++ return info; ++ } ++ ++ content::BrowserContext* context_; ++}; ++ ++void AdblockPrivateAPI::Shutdown() { ++ // EventRouter can be null in tests ++ if (EventRouter::Get(context_)) { ++ EventRouter::Get(context_)->UnregisterObserver(this); ++ } ++ event_router_.reset(); ++} ++ ++// static ++AdblockPrivateAPI* AdblockPrivateAPI::Get(content::BrowserContext* context) { ++ return GetFactoryInstance()->Get(context); ++} ++ ++AdblockPrivateAPI::AdblockPrivateAPI(content::BrowserContext* context) ++ : context_(context) { ++ // EventRouter can be null in tests ++ if (EventRouter::Get(context_)) { ++ EventRouter::Get(context_)->RegisterObserver( ++ this, api::adblock_private::OnAdAllowed::kEventName); ++ EventRouter::Get(context_)->RegisterObserver( ++ this, api::adblock_private::OnAdBlocked::kEventName); ++ EventRouter::Get(context_)->RegisterObserver( ++ this, api::adblock_private::OnPageAllowed::kEventName); ++ EventRouter::Get(context_)->RegisterObserver( ++ this, api::adblock_private::OnPopupAllowed::kEventName); ++ EventRouter::Get(context_)->RegisterObserver( ++ this, api::adblock_private::OnPopupBlocked::kEventName); ++ EventRouter::Get(context_)->RegisterObserver( ++ this, api::adblock_private::OnSubscriptionUpdated::kEventName); ++ } ++ adblock::SessionStatsFactory::GetForBrowserContext(context) ++ ->StartCollectingStats(); ++} ++ ++AdblockPrivateAPI::~AdblockPrivateAPI() = default; ++ ++void AdblockPrivateAPI::OnListenerAdded( ++ const extensions::EventListenerInfo& details) { ++ event_router_ = ++ std::make_unique(context_); ++ EventRouter::Get(context_)->UnregisterObserver(this); ++} ++ ++namespace api { ++ ++AdblockPrivateSetUpdateConsentFunction:: ++ AdblockPrivateSetUpdateConsentFunction() {} ++ ++AdblockPrivateSetUpdateConsentFunction:: ++ ~AdblockPrivateSetUpdateConsentFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateSetUpdateConsentFunction::Run() { ++ std::unique_ptr params( ++ api::adblock_private::SetUpdateConsent::Params::Create(args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ switch (params->consent) { ++ case api::adblock_private::UpdateConsent::UPDATE_CONSENT_WIFI_ONLY: ++ controller->SetUpdateConsent(adblock::AllowedConnectionType::kWiFi); ++ break; ++ case api::adblock_private::UpdateConsent::UPDATE_CONSENT_ALWAYS: ++ controller->SetUpdateConsent(adblock::AllowedConnectionType::kAny); ++ break; ++ default: ++ NOTREACHED(); ++ } ++ ++ return RespondNow(NoArguments()); ++} ++ ++AdblockPrivateGetUpdateConsentFunction:: ++ AdblockPrivateGetUpdateConsentFunction() {} ++ ++AdblockPrivateGetUpdateConsentFunction:: ++ ~AdblockPrivateGetUpdateConsentFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateGetUpdateConsentFunction::Run() { ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ ++ auto consent = controller->GetUpdateConsent(); ++ api::adblock_private::UpdateConsent result = ++ api::adblock_private::UpdateConsent::UPDATE_CONSENT_NONE; ++ switch (consent) { ++ case adblock::AllowedConnectionType::kWiFi: ++ result = api::adblock_private::UpdateConsent::UPDATE_CONSENT_WIFI_ONLY; ++ break; ++ case adblock::AllowedConnectionType::kAny: ++ result = api::adblock_private::UpdateConsent::UPDATE_CONSENT_ALWAYS; ++ break; ++ // TODO what about NONE? This will trigger a dcheck... ++ default: ++ NOTREACHED(); ++ } ++ ++ return RespondNow(ArgumentList( ++ api::adblock_private::GetUpdateConsent::Results::Create(result))); ++} ++ ++AdblockPrivateSetEnabledFunction::AdblockPrivateSetEnabledFunction() {} ++ ++AdblockPrivateSetEnabledFunction::~AdblockPrivateSetEnabledFunction() {} ++ ++ExtensionFunction::ResponseAction AdblockPrivateSetEnabledFunction::Run() { ++ std::unique_ptr params( ++ api::adblock_private::SetEnabled::Params::Create(args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ controller->SetAdblockEnabled(params->enabled); ++ return RespondNow(NoArguments()); ++} ++ ++AdblockPrivateIsEnabledFunction::AdblockPrivateIsEnabledFunction() {} ++ ++AdblockPrivateIsEnabledFunction::~AdblockPrivateIsEnabledFunction() {} ++ ++ExtensionFunction::ResponseAction AdblockPrivateIsEnabledFunction::Run() { ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ return RespondNow( ++ ArgumentList(api::adblock_private::IsEnabled::Results::Create( ++ controller->IsAdblockEnabled()))); ++} ++ ++AdblockPrivateSetAcceptableAdsEnabledFunction:: ++ AdblockPrivateSetAcceptableAdsEnabledFunction() {} ++ ++AdblockPrivateSetAcceptableAdsEnabledFunction:: ++ ~AdblockPrivateSetAcceptableAdsEnabledFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateSetAcceptableAdsEnabledFunction::Run() { ++ std::unique_ptr params( ++ api::adblock_private::SetAcceptableAdsEnabled::Params::Create(args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ controller->SetAcceptableAdsEnabled(params->enabled); ++ ++ return RespondNow(NoArguments()); ++} ++ ++AdblockPrivateIsAcceptableAdsEnabledFunction:: ++ AdblockPrivateIsAcceptableAdsEnabledFunction() {} ++ ++AdblockPrivateIsAcceptableAdsEnabledFunction:: ++ ~AdblockPrivateIsAcceptableAdsEnabledFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateIsAcceptableAdsEnabledFunction::Run() { ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ return RespondNow(ArgumentList( ++ api::adblock_private::IsAcceptableAdsEnabled::Results::Create( ++ controller->IsAcceptableAdsEnabled()))); ++} ++ ++AdblockPrivateGetBuiltInSubscriptionsFunction:: ++ AdblockPrivateGetBuiltInSubscriptionsFunction() {} ++ ++AdblockPrivateGetBuiltInSubscriptionsFunction:: ++ ~AdblockPrivateGetBuiltInSubscriptionsFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateGetBuiltInSubscriptionsFunction::Run() { ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ auto recommended = controller->GetKnownSubscriptions(); ++ std::vector result; ++ for (auto& recommended_one : recommended) { ++ if (recommended_one.ui_visibility == ++ adblock::SubscriptionUiVisibility::Visible) { ++ api::adblock_private::BuiltInSubscription js_recommended; ++ js_recommended.url = recommended_one.url.spec(); ++ js_recommended.title = recommended_one.title; ++ js_recommended.languages = recommended_one.languages; ++ result.emplace_back(std::move(js_recommended)); ++ } ++ } ++ return RespondNow(ArgumentList( ++ api::adblock_private::GetBuiltInSubscriptions::Results::Create(result))); ++} ++ ++AdblockPrivateSelectBuiltInSubscriptionFunction:: ++ AdblockPrivateSelectBuiltInSubscriptionFunction() {} ++ ++AdblockPrivateSelectBuiltInSubscriptionFunction:: ++ ~AdblockPrivateSelectBuiltInSubscriptionFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateSelectBuiltInSubscriptionFunction::Run() { ++ std::unique_ptr ++ params(api::adblock_private::SelectBuiltInSubscription::Params::Create( ++ args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ auto url = GURL{params->url}; ++ auto status = RunBuiltInSubscriptionAction(BuiltInSubscriptionAction::kSelect, ++ browser_context(), url); ++ if (!status.empty()) ++ return RespondNow(Error(status)); ++ ++ return RespondNow(NoArguments()); ++} ++ ++AdblockPrivateUnselectBuiltInSubscriptionFunction:: ++ AdblockPrivateUnselectBuiltInSubscriptionFunction() {} ++ ++AdblockPrivateUnselectBuiltInSubscriptionFunction:: ++ ~AdblockPrivateUnselectBuiltInSubscriptionFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateUnselectBuiltInSubscriptionFunction::Run() { ++ std::unique_ptr ++ params(api::adblock_private::UnselectBuiltInSubscription::Params::Create( ++ args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ auto url = GURL{params->url}; ++ auto status = RunBuiltInSubscriptionAction( ++ BuiltInSubscriptionAction::kUnselect, browser_context(), url); ++ if (!status.empty()) ++ return RespondNow(Error(status)); ++ ++ return RespondNow(NoArguments()); ++} ++ ++AdblockPrivateGetSelectedBuiltInSubscriptionsFunction:: ++ AdblockPrivateGetSelectedBuiltInSubscriptionsFunction() {} ++ ++AdblockPrivateGetSelectedBuiltInSubscriptionsFunction:: ++ ~AdblockPrivateGetSelectedBuiltInSubscriptionsFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateGetSelectedBuiltInSubscriptionsFunction::Run() { ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ ++ return RespondNow(ArgumentList( ++ api::adblock_private::GetSelectedBuiltInSubscriptions::Results::Create( ++ CopySubscriptions(controller->GetSelectedBuiltInSubscriptions())))); ++} ++ ++AdblockPrivateAddCustomSubscriptionFunction:: ++ AdblockPrivateAddCustomSubscriptionFunction() {} ++ ++AdblockPrivateAddCustomSubscriptionFunction:: ++ ~AdblockPrivateAddCustomSubscriptionFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateAddCustomSubscriptionFunction::Run() { ++ std::unique_ptr params( ++ api::adblock_private::AddCustomSubscription::Params::Create(args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ auto url = GURL{params->url}; ++ auto status = RunCustomSubscriptionAction(CustomSubscriptionAction::kAdd, ++ browser_context(), url); ++ if (!status.empty()) ++ return RespondNow(Error(status)); ++ ++ return RespondNow(NoArguments()); ++} ++ ++AdblockPrivateRemoveCustomSubscriptionFunction:: ++ AdblockPrivateRemoveCustomSubscriptionFunction() {} ++ ++AdblockPrivateRemoveCustomSubscriptionFunction:: ++ ~AdblockPrivateRemoveCustomSubscriptionFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateRemoveCustomSubscriptionFunction::Run() { ++ std::unique_ptr ++ params(api::adblock_private::RemoveCustomSubscription::Params::Create( ++ args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ auto url = GURL{params->url}; ++ auto status = RunCustomSubscriptionAction(CustomSubscriptionAction::kRemove, ++ browser_context(), url); ++ if (!status.empty()) ++ return RespondNow(Error(status)); ++ ++ return RespondNow(NoArguments()); ++} ++ ++AdblockPrivateGetCustomSubscriptionsFunction:: ++ AdblockPrivateGetCustomSubscriptionsFunction() {} ++ ++AdblockPrivateGetCustomSubscriptionsFunction:: ++ ~AdblockPrivateGetCustomSubscriptionsFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateGetCustomSubscriptionsFunction::Run() { ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ return RespondNow(ArgumentList( ++ api::adblock_private::GetCustomSubscriptions::Results::Create( ++ CopySubscriptions(controller->GetCustomSubscriptions())))); ++} ++ ++AdblockPrivateAddAllowedDomainFunction:: ++ AdblockPrivateAddAllowedDomainFunction() {} ++ ++AdblockPrivateAddAllowedDomainFunction:: ++ ~AdblockPrivateAddAllowedDomainFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateAddAllowedDomainFunction::Run() { ++ std::unique_ptr params( ++ api::adblock_private::AddAllowedDomain::Params::Create(args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ controller->AddAllowedDomain(params->domain); ++ return RespondNow(NoArguments()); ++} ++ ++AdblockPrivateRemoveAllowedDomainFunction:: ++ AdblockPrivateRemoveAllowedDomainFunction() {} ++ ++AdblockPrivateRemoveAllowedDomainFunction:: ++ ~AdblockPrivateRemoveAllowedDomainFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateRemoveAllowedDomainFunction::Run() { ++ std::unique_ptr params( ++ api::adblock_private::RemoveAllowedDomain::Params::Create(args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ controller->RemoveAllowedDomain(params->domain); ++ ++ return RespondNow(NoArguments()); ++} ++ ++AdblockPrivateGetAllowedDomainsFunction:: ++ AdblockPrivateGetAllowedDomainsFunction() {} ++ ++AdblockPrivateGetAllowedDomainsFunction:: ++ ~AdblockPrivateGetAllowedDomainsFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateGetAllowedDomainsFunction::Run() { ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ return RespondNow( ++ ArgumentList(api::adblock_private::GetAllowedDomains::Results::Create( ++ controller->GetAllowedDomains()))); ++} ++ ++AdblockPrivateAddCustomFilterFunction::AdblockPrivateAddCustomFilterFunction() { ++} ++ ++AdblockPrivateAddCustomFilterFunction:: ++ ~AdblockPrivateAddCustomFilterFunction() {} ++ ++ExtensionFunction::ResponseAction AdblockPrivateAddCustomFilterFunction::Run() { ++ std::unique_ptr params( ++ api::adblock_private::AddCustomFilter::Params::Create(args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ controller->AddCustomFilter(params->filter); ++ return RespondNow(NoArguments()); ++} ++ ++AdblockPrivateRemoveCustomFilterFunction:: ++ AdblockPrivateRemoveCustomFilterFunction() {} ++ ++AdblockPrivateRemoveCustomFilterFunction:: ++ ~AdblockPrivateRemoveCustomFilterFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateRemoveCustomFilterFunction::Run() { ++ std::unique_ptr params( ++ api::adblock_private::RemoveCustomFilter::Params::Create(args())); ++ EXTENSION_FUNCTION_VALIDATE(params); ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser_context()); ++ controller->RemoveCustomFilter(params->filter); ++ return RespondNow(NoArguments()); ++} ++ ++AdblockPrivateGetSessionAllowedAdsCountFunction:: ++ AdblockPrivateGetSessionAllowedAdsCountFunction() {} ++ ++AdblockPrivateGetSessionAllowedAdsCountFunction:: ++ ~AdblockPrivateGetSessionAllowedAdsCountFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateGetSessionAllowedAdsCountFunction::Run() { ++ auto* session_stats_ = ++ adblock::SessionStatsFactory::GetForBrowserContext(browser_context()); ++ return RespondNow(ArgumentList( ++ api::adblock_private::GetSessionAllowedAdsCount::Results::Create( ++ CopySessionsStats(session_stats_->GetSessionAllowedAdsCount())))); ++} ++ ++AdblockPrivateGetSessionBlockedAdsCountFunction:: ++ AdblockPrivateGetSessionBlockedAdsCountFunction() {} ++ ++AdblockPrivateGetSessionBlockedAdsCountFunction:: ++ ~AdblockPrivateGetSessionBlockedAdsCountFunction() {} ++ ++ExtensionFunction::ResponseAction ++AdblockPrivateGetSessionBlockedAdsCountFunction::Run() { ++ auto* session_stats_ = ++ adblock::SessionStatsFactory::GetForBrowserContext(browser_context()); ++ return RespondNow(ArgumentList( ++ api::adblock_private::GetSessionAllowedAdsCount::Results::Create( ++ CopySessionsStats(session_stats_->GetSessionBlockedAdsCount())))); ++} ++ ++} // namespace api ++} // namespace extensions +diff --git a/chrome/browser/extensions/api/adblock_private/adblock_private_api.h b/chrome/browser/extensions/api/adblock_private/adblock_private_api.h +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/extensions/api/adblock_private/adblock_private_api.h +@@ -0,0 +1,412 @@ ++// 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 . ++ ++#ifndef CHROME_BROWSER_EXTENSIONS_API_ADBLOCK_PRIVATE_ADBLOCK_PRIVATE_API_H_ ++#define CHROME_BROWSER_EXTENSIONS_API_ADBLOCK_PRIVATE_ADBLOCK_PRIVATE_API_H_ ++ ++#include "chrome/common/extensions/api/adblock_private.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "extensions/browser/browser_context_keyed_api_factory.h" ++#include "extensions/browser/event_router.h" ++#include "extensions/browser/extension_function.h" ++ ++class Profile; ++ ++namespace extensions { ++ ++class AdblockPrivateAPI : public BrowserContextKeyedAPI, ++ public EventRouter::Observer { ++ public: ++ static BrowserContextKeyedAPIFactory* GetFactoryInstance(); ++ ++ static AdblockPrivateAPI* Get(content::BrowserContext* context); ++ ++ explicit AdblockPrivateAPI(content::BrowserContext* context); ++ ~AdblockPrivateAPI() override; ++ friend class BrowserContextKeyedAPIFactory; ++ ++ // BrowserContextKeyedAPI implementation. ++ static const char* service_name() { return "AdblockPrivateAPI"; } ++ static const bool kServiceRedirectedInIncognito = true; ++ static const bool kServiceIsCreatedWithBrowserContext = true; ++ void Shutdown() override; ++ ++ // EventRouter::Observer: ++ void OnListenerAdded(const extensions::EventListenerInfo& details) override; ++ ++ private: ++ content::BrowserContext* context_; ++ class AdblockAPIEventRouter; ++ std::unique_ptr event_router_; ++}; ++ ++template <> ++void BrowserContextKeyedAPIFactory< ++ AdblockPrivateAPI>::DeclareFactoryDependencies(); ++ ++namespace api { ++ ++class AdblockPrivateSetUpdateConsentFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.setUpdateConsent", ++ ADBLOCKPRIVATE_SETUPDATECONSENT) ++ AdblockPrivateSetUpdateConsentFunction(); ++ ++ private: ++ ~AdblockPrivateSetUpdateConsentFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateSetUpdateConsentFunction( ++ const AdblockPrivateSetUpdateConsentFunction&) = delete; ++ AdblockPrivateSetUpdateConsentFunction& operator=( ++ const AdblockPrivateSetUpdateConsentFunction&) = delete; ++}; ++ ++class AdblockPrivateGetUpdateConsentFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.getUpdateConsent", ++ ADBLOCKPRIVATE_GETUPDATECONSENT) ++ AdblockPrivateGetUpdateConsentFunction(); ++ ++ private: ++ ~AdblockPrivateGetUpdateConsentFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateGetUpdateConsentFunction( ++ const AdblockPrivateGetUpdateConsentFunction&) = delete; ++ AdblockPrivateGetUpdateConsentFunction& operator=( ++ const AdblockPrivateGetUpdateConsentFunction&) = delete; ++}; ++ ++class AdblockPrivateSetEnabledFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.setEnabled", ++ ADBLOCKPRIVATE_SETENABLED) ++ AdblockPrivateSetEnabledFunction(); ++ ++ private: ++ ~AdblockPrivateSetEnabledFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateSetEnabledFunction(const AdblockPrivateSetEnabledFunction&) = ++ delete; ++ AdblockPrivateSetEnabledFunction& operator=( ++ const AdblockPrivateSetEnabledFunction&) = delete; ++}; ++ ++class AdblockPrivateIsEnabledFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.isEnabled", ++ ADBLOCKPRIVATE_ISENABLED) ++ AdblockPrivateIsEnabledFunction(); ++ ++ private: ++ ~AdblockPrivateIsEnabledFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateIsEnabledFunction(const AdblockPrivateIsEnabledFunction&) = ++ delete; ++ AdblockPrivateIsEnabledFunction& operator=( ++ const AdblockPrivateIsEnabledFunction&) = delete; ++}; ++ ++class AdblockPrivateSetAcceptableAdsEnabledFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.setAcceptableAdsEnabled", ++ ADBLOCKPRIVATE_SETACCEPTABLEADSENABLED) ++ AdblockPrivateSetAcceptableAdsEnabledFunction(); ++ ++ private: ++ ~AdblockPrivateSetAcceptableAdsEnabledFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateSetAcceptableAdsEnabledFunction( ++ const AdblockPrivateSetAcceptableAdsEnabledFunction&) = delete; ++ AdblockPrivateSetAcceptableAdsEnabledFunction& operator=( ++ const AdblockPrivateSetAcceptableAdsEnabledFunction&) = delete; ++}; ++ ++class AdblockPrivateIsAcceptableAdsEnabledFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.isAcceptableAdsEnabled", ++ ADBLOCKPRIVATE_ISACCEPTABLEADSENABLED) ++ AdblockPrivateIsAcceptableAdsEnabledFunction(); ++ ++ private: ++ ~AdblockPrivateIsAcceptableAdsEnabledFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateIsAcceptableAdsEnabledFunction( ++ const AdblockPrivateIsAcceptableAdsEnabledFunction&) = delete; ++ AdblockPrivateIsAcceptableAdsEnabledFunction& operator=( ++ const AdblockPrivateIsAcceptableAdsEnabledFunction&) = delete; ++}; ++ ++class AdblockPrivateGetBuiltInSubscriptionsFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.getBuiltInSubscriptions", ++ ADBLOCKPRIVATE_GETBUILTINSUBSCRIPTIONS) ++ AdblockPrivateGetBuiltInSubscriptionsFunction(); ++ ++ private: ++ ~AdblockPrivateGetBuiltInSubscriptionsFunction() override; ++ ++ // ExtensionFunction: ++ ResponseAction Run() override; ++ ++ AdblockPrivateGetBuiltInSubscriptionsFunction( ++ const AdblockPrivateGetBuiltInSubscriptionsFunction&) = delete; ++ AdblockPrivateGetBuiltInSubscriptionsFunction& operator=( ++ const AdblockPrivateGetBuiltInSubscriptionsFunction&) = delete; ++}; ++ ++class AdblockPrivateSelectBuiltInSubscriptionFunction ++ : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.selectBuiltInSubscription", ++ ADBLOCKPRIVATE_SELECTBUILTINSUBSCRIPTION) ++ AdblockPrivateSelectBuiltInSubscriptionFunction(); ++ ++ private: ++ ~AdblockPrivateSelectBuiltInSubscriptionFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateSelectBuiltInSubscriptionFunction( ++ const AdblockPrivateSelectBuiltInSubscriptionFunction&) = delete; ++ AdblockPrivateSelectBuiltInSubscriptionFunction& operator=( ++ const AdblockPrivateSelectBuiltInSubscriptionFunction&) = delete; ++}; ++ ++class AdblockPrivateUnselectBuiltInSubscriptionFunction ++ : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.unselectBuiltInSubscription", ++ ADBLOCKPRIVATE_UNSELECTBUILTINSUBSCRIPTION) ++ AdblockPrivateUnselectBuiltInSubscriptionFunction(); ++ ++ private: ++ ~AdblockPrivateUnselectBuiltInSubscriptionFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateUnselectBuiltInSubscriptionFunction( ++ const AdblockPrivateUnselectBuiltInSubscriptionFunction&) = delete; ++ AdblockPrivateUnselectBuiltInSubscriptionFunction& operator=( ++ const AdblockPrivateUnselectBuiltInSubscriptionFunction&) = delete; ++}; ++ ++class AdblockPrivateGetSelectedBuiltInSubscriptionsFunction ++ : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.getSelectedBuiltInSubscriptions", ++ ADBLOCKPRIVATE_GETSELECTEDBUILTINSUBSCRIPTIONS) ++ AdblockPrivateGetSelectedBuiltInSubscriptionsFunction(); ++ ++ private: ++ ~AdblockPrivateGetSelectedBuiltInSubscriptionsFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateGetSelectedBuiltInSubscriptionsFunction( ++ const AdblockPrivateGetSelectedBuiltInSubscriptionsFunction&) = delete; ++ AdblockPrivateGetSelectedBuiltInSubscriptionsFunction& operator=( ++ const AdblockPrivateGetSelectedBuiltInSubscriptionsFunction&) = delete; ++}; ++ ++class AdblockPrivateAddCustomSubscriptionFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.addCustomSubscription", ++ ADBLOCKPRIVATE_ADDCUSTOMSUBSCRIPTION) ++ AdblockPrivateAddCustomSubscriptionFunction(); ++ ++ private: ++ ~AdblockPrivateAddCustomSubscriptionFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateAddCustomSubscriptionFunction( ++ const AdblockPrivateAddCustomSubscriptionFunction&) = delete; ++ AdblockPrivateAddCustomSubscriptionFunction& operator=( ++ const AdblockPrivateAddCustomSubscriptionFunction&) = delete; ++}; ++ ++class AdblockPrivateRemoveCustomSubscriptionFunction ++ : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.removeCustomSubscription", ++ ADBLOCKPRIVATE_REMOVECUSTOMSUBSCRIPTION) ++ AdblockPrivateRemoveCustomSubscriptionFunction(); ++ ++ private: ++ ~AdblockPrivateRemoveCustomSubscriptionFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateRemoveCustomSubscriptionFunction( ++ const AdblockPrivateRemoveCustomSubscriptionFunction&) = delete; ++ AdblockPrivateRemoveCustomSubscriptionFunction& operator=( ++ const AdblockPrivateRemoveCustomSubscriptionFunction&) = delete; ++}; ++ ++class AdblockPrivateGetCustomSubscriptionsFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.getCustomSubscriptions", ++ ADBLOCKPRIVATE_GETCUSTOMSUBSCRIPTIONS) ++ AdblockPrivateGetCustomSubscriptionsFunction(); ++ ++ private: ++ ~AdblockPrivateGetCustomSubscriptionsFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateGetCustomSubscriptionsFunction( ++ const AdblockPrivateGetCustomSubscriptionsFunction&) = delete; ++ AdblockPrivateGetCustomSubscriptionsFunction& operator=( ++ const AdblockPrivateGetCustomSubscriptionsFunction&) = delete; ++}; ++ ++class AdblockPrivateAddAllowedDomainFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.addAllowedDomain", ++ ADBLOCKPRIVATE_ADDALLOWEDDOMAIN) ++ AdblockPrivateAddAllowedDomainFunction(); ++ ++ private: ++ ~AdblockPrivateAddAllowedDomainFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateAddAllowedDomainFunction( ++ const AdblockPrivateAddAllowedDomainFunction&) = delete; ++ AdblockPrivateAddAllowedDomainFunction& operator=( ++ const AdblockPrivateAddAllowedDomainFunction&) = delete; ++}; ++ ++class AdblockPrivateRemoveAllowedDomainFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.removeAllowedDomain", ++ ADBLOCKPRIVATE_REMOVEALLOWEDDOMAIN) ++ AdblockPrivateRemoveAllowedDomainFunction(); ++ ++ private: ++ ~AdblockPrivateRemoveAllowedDomainFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateRemoveAllowedDomainFunction( ++ const AdblockPrivateRemoveAllowedDomainFunction&) = delete; ++ AdblockPrivateRemoveAllowedDomainFunction& operator=( ++ const AdblockPrivateRemoveAllowedDomainFunction&) = delete; ++}; ++ ++class AdblockPrivateGetAllowedDomainsFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.getAllowedDomains", ++ ADBLOCKPRIVATE_GETALLOWEDDOMAINS) ++ AdblockPrivateGetAllowedDomainsFunction(); ++ ++ private: ++ ~AdblockPrivateGetAllowedDomainsFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateGetAllowedDomainsFunction( ++ const AdblockPrivateGetAllowedDomainsFunction&) = delete; ++ AdblockPrivateGetAllowedDomainsFunction& operator=( ++ const AdblockPrivateGetAllowedDomainsFunction&) = delete; ++}; ++ ++class AdblockPrivateAddCustomFilterFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.addCustomFilter", ++ ADBLOCKPRIVATE_ADDCUSTOMFILTER) ++ AdblockPrivateAddCustomFilterFunction(); ++ ++ private: ++ ~AdblockPrivateAddCustomFilterFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateAddCustomFilterFunction( ++ const AdblockPrivateAddCustomFilterFunction&) = delete; ++ AdblockPrivateAddCustomFilterFunction& operator=( ++ const AdblockPrivateAddCustomFilterFunction&) = delete; ++}; ++ ++class AdblockPrivateRemoveCustomFilterFunction : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.removeCustomFilter", ++ ADBLOCKPRIVATE_REMOVECUSTOMFILTER) ++ AdblockPrivateRemoveCustomFilterFunction(); ++ ++ private: ++ ~AdblockPrivateRemoveCustomFilterFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateRemoveCustomFilterFunction( ++ const AdblockPrivateRemoveCustomFilterFunction&) = delete; ++ AdblockPrivateRemoveCustomFilterFunction& operator=( ++ const AdblockPrivateRemoveCustomFilterFunction&) = delete; ++}; ++ ++class AdblockPrivateGetSessionAllowedAdsCountFunction ++ : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.getSessionAllowedAdsCount", ++ ADBLOCKPRIVATE_GETSESSIONALLOWEDADSCOUNT) ++ AdblockPrivateGetSessionAllowedAdsCountFunction(); ++ ++ private: ++ ~AdblockPrivateGetSessionAllowedAdsCountFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateGetSessionAllowedAdsCountFunction( ++ const AdblockPrivateGetSessionAllowedAdsCountFunction&) = delete; ++ AdblockPrivateGetSessionAllowedAdsCountFunction& operator=( ++ const AdblockPrivateGetSessionAllowedAdsCountFunction&) = delete; ++}; ++ ++class AdblockPrivateGetSessionBlockedAdsCountFunction ++ : public ExtensionFunction { ++ public: ++ DECLARE_EXTENSION_FUNCTION("adblockPrivate.getSessionBlockedAdsCount", ++ ADBLOCKPRIVATE_GETSESSIONBLOCKEDADSCOUNT) ++ AdblockPrivateGetSessionBlockedAdsCountFunction(); ++ ++ private: ++ ~AdblockPrivateGetSessionBlockedAdsCountFunction() override; ++ ++ ResponseAction Run() override; ++ ++ AdblockPrivateGetSessionBlockedAdsCountFunction( ++ const AdblockPrivateGetSessionBlockedAdsCountFunction&) = delete; ++ AdblockPrivateGetSessionBlockedAdsCountFunction& operator=( ++ const AdblockPrivateGetSessionBlockedAdsCountFunction&) = delete; ++}; ++ ++} // namespace api ++ ++} // namespace extensions ++ ++#endif // CHROME_BROWSER_EXTENSIONS_API_ADBLOCK_PRIVATE_ADBLOCK_PRIVATE_API_H_ +diff --git a/chrome/browser/extensions/api/adblock_private/adblock_private_apitest.cc b/chrome/browser/extensions/api/adblock_private/adblock_private_apitest.cc +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/extensions/api/adblock_private/adblock_private_apitest.cc +@@ -0,0 +1,469 @@ ++// 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 . ++ ++#include ++#include ++#include ++ ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/extensions/extension_apitest.h" ++#include "chrome/common/extensions/api/adblock_private.h" ++#include "chrome/common/extensions/api/tabs.h" ++#include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/core/adblock_controller.h" ++#include "components/adblock/core/common/adblock_constants.h" ++#include "content/public/test/browser_test.h" ++#include "extensions/browser/background_script_executor.h" ++#include "net/dns/mock_host_resolver.h" ++#include "net/test/embedded_test_server/embedded_test_server.h" ++#include "net/test/embedded_test_server/http_request.h" ++#include "net/test/embedded_test_server/http_response.h" ++#include "testing/gmock/include/gmock/gmock.h" ++#include "testing/gtest/include/gtest/gtest.h" ++ ++using testing::_; ++using testing::Mock; ++using testing::Return; ++ ++namespace extensions { ++ ++namespace { ++ ++std::unique_ptr HandleSubscriptionUpdateRequest( ++ const std::string subcription_path, ++ const std::string subcription_filters, ++ const net::test_server::HttpRequest& request) { ++ static const char kSubscriptionHeader[] = ++ "[Adblock Plus 2.0]\n" ++ "! Checksum: X5A8vtJDBW2a9EgS9glqbg\n" ++ "! Version: 202202061935\n" ++ "! Last modified: 06 Feb 2022 19:35 UTC\n" ++ "! Expires: 1 days (update frequency)\n\n"; ++ ++ if (base::StartsWith(request.relative_url, subcription_path, ++ base::CompareCase::SENSITIVE)) { ++ auto http_response = ++ std::make_unique(); ++ http_response->set_code(net::HTTP_OK); ++ http_response->set_content(kSubscriptionHeader + subcription_filters); ++ http_response->set_content_type("text/plain"); ++ return std::move(http_response); ++ } ++ ++ // Unhandled requests result in the Embedded test server sending a 404. ++ return nullptr; ++} ++ ++class AdblockPrivateApiTest : public ExtensionApiTest { ++ public: ++ AdblockPrivateApiTest() {} ++ ~AdblockPrivateApiTest() override = default; ++ AdblockPrivateApiTest(const AdblockPrivateApiTest&) = delete; ++ AdblockPrivateApiTest& operator=(const AdblockPrivateApiTest&) = delete; ++ ++ protected: ++ void SetUpOnMainThread() override { ++ ExtensionApiTest::SetUpOnMainThread(); ++ ++ // When any of that fails we need to update comment in adblock_private.idl ++ ASSERT_EQ(api::tabs::TAB_ID_NONE, -1); ++ ASSERT_EQ(SessionID::InvalidValue().id(), -1); ++ ++ adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser()->profile()) ++ ->RemoveCustomFilter(adblock::kAllowlistEverythingFilter); ++ } ++ ++ bool RunTest(const std::string& subtest) { ++ const std::string page_url = "main.html?" + subtest; ++ return RunExtensionTest("adblock_private", {.page_url = page_url.c_str()}, ++ {.load_as_component = true}); ++ } ++ ++ bool RunTestWithParams(const std::string& subtest, ++ const std::map& params) { ++ if (params.empty()) { ++ return RunTest(subtest); ++ } ++ std::string subtest_with_params = subtest; ++ for (const auto& [key, value] : params) { ++ subtest_with_params += "&" + key + "=" + value; ++ } ++ return RunTest(subtest_with_params); ++ } ++ ++ bool RunTestWithServer(const std::string& subtest, ++ const std::string& subcription_path, ++ const std::string& subcription_filters) { ++ net::EmbeddedTestServer https_server{ ++ net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS)}; ++ https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK); ++ https_server.RegisterRequestHandler( ++ base::BindRepeating(&HandleSubscriptionUpdateRequest, subcription_path, ++ subcription_filters)); ++ if (!https_server.Start()) { ++ return false; ++ } ++ const std::string subtest_with_params = ++ subtest + ++ "&subscription_url=" + https_server.GetURL(subcription_path).spec(); ++ return RunTest(subtest_with_params); ++ } ++}; ++ ++} // namespace ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, UpdateConsent) { ++ EXPECT_TRUE(RunTest("updateConsent")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, SetAndCheckEnabled) { ++ EXPECT_TRUE(RunTest("setEnabled_isEnabled")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, SetAndCheckAAEnabled) { ++ EXPECT_TRUE(RunTest("setAAEnabled_isAAEnabled")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, GetBuiltInSubscriptions) { ++ EXPECT_TRUE(RunTest("getBuiltInSubscriptions")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, SelectedSubscriptionsDataSchema) { ++ EXPECT_TRUE(RunTest("selectedSubscriptionsDataSchema")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, ++ SelectBuiltInSubscriptionsInvalidURL) { ++ EXPECT_TRUE(RunTest("selectBuiltInSubscriptionsInvalidURL")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, ++ SelectBuiltInSubscriptionsNotBuiltIn) { ++ EXPECT_TRUE(RunTest("selectBuiltInSubscriptionsNotBuiltIn")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, ++ UnselectBuiltInSubscriptionsInvalidURL) { ++ EXPECT_TRUE(RunTest("unselectBuiltInSubscriptionsInvalidURL")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, ++ UnselectBuiltInSubscriptionsNotBuiltIn) { ++ EXPECT_TRUE(RunTest("unselectBuiltInSubscriptionsNotBuiltIn")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, BuiltInSubscriptionsManagement) { ++ DCHECK(browser()->profile()); ++ auto* controller = adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser()->profile()); ++ auto selected = controller->GetSelectedBuiltInSubscriptions(); ++ const auto easylist = std::find_if( ++ selected.begin(), selected.end(), ++ [&](scoped_refptr subscription) { ++ return base::EndsWith(subscription->GetSourceUrl().path_piece(), ++ "easylist.txt"); ++ }); ++ const auto exceptions = std::find_if( ++ selected.begin(), selected.end(), ++ [&](scoped_refptr subscription) { ++ return base::EndsWith(subscription->GetSourceUrl().path_piece(), ++ "exceptionrules.txt"); ++ }); ++ const auto snippets = std::find_if( ++ selected.begin(), selected.end(), ++ [&](scoped_refptr subscription) { ++ return base::EndsWith(subscription->GetSourceUrl().path_piece(), ++ "abp-filters-anti-cv.txt"); ++ }); ++ if (easylist == selected.end() || exceptions == selected.end() || ++ snippets == selected.end()) { ++ // Since default configuration has been changed let's skip this test ++ return; ++ } ++ const std::map params = { ++ {"easylist", (*easylist)->GetSourceUrl().spec()}, ++ {"exceptions", (*exceptions)->GetSourceUrl().spec()}, ++ {"snippets", (*snippets)->GetSourceUrl().spec()}}; ++ EXPECT_TRUE(RunTestWithParams("builtInSubscriptionsManagement", params)) ++ << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, CustomSubscriptionInvalidURL) { ++ EXPECT_TRUE(RunTest("addCustomSubscriptionInvalidURL")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, RemoveSubscriptionInvalidURL) { ++ EXPECT_TRUE(RunTest("removeCustomSubscriptionInvalidURL")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, CustomSubscriptionsManagement) { ++ EXPECT_TRUE(RunTest("customSubscriptionsManagement")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, AllowedDomainsManagement) { ++ EXPECT_TRUE(RunTest("allowedDomainsManagement")) << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, AdBlockedEvents) { ++ std::string subcription_path = "/testeventssub.txt"; ++ std::string subcription_filters = "test1.png"; ++ ++ EXPECT_TRUE(RunTestWithServer("adBlockedEvents", subcription_path, ++ subcription_filters)) ++ << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, AdAllowedEvents) { ++ std::string subcription_path = "/testeventssub.txt"; ++ std::string subcription_filters = "test2.png\n@@test2.png"; ++ ++ EXPECT_TRUE(RunTestWithServer("adAllowedEvents", subcription_path, ++ subcription_filters)) ++ << message_; ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiTest, SessionStats) { ++ std::string subcription_path = "/teststatssub.txt"; ++ std::string subcription_filters = "test3.png\ntest4.png\n@@test4.png"; ++ ++ EXPECT_TRUE( ++ RunTestWithServer("sessionStats", subcription_path, subcription_filters)) ++ << message_; ++} ++ ++class AdblockPrivateApiBackgroundPageTest : public ExtensionApiTest { ++ public: ++ AdblockPrivateApiBackgroundPageTest() {} ++ ~AdblockPrivateApiBackgroundPageTest() override = default; ++ AdblockPrivateApiBackgroundPageTest( ++ const AdblockPrivateApiBackgroundPageTest&) = delete; ++ AdblockPrivateApiBackgroundPageTest& operator=( ++ const AdblockPrivateApiBackgroundPageTest&) = delete; ++ ++ protected: ++ void SetUpOnMainThread() override { ++ ExtensionApiTest::SetUpOnMainThread(); ++ ++ // Map example.com to localhost. ++ host_resolver()->AddRule("example.com", "127.0.0.1"); ++ ASSERT_TRUE(StartEmbeddedTestServer()); ++ adblock::AdblockControllerFactory::GetForBrowserContext( ++ browser()->profile()) ++ ->RemoveCustomFilter(adblock::kAllowlistEverythingFilter); ++ } ++ ++ void ExecuteScript(const std::string& js_code) const { ++ content::WebContents* web_contents = ++ browser()->tab_strip_model()->GetActiveWebContents(); ++ ASSERT_TRUE(content::ExecJs(web_contents->GetPrimaryMainFrame(), js_code)); ++ } ++}; ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiBackgroundPageTest, PageAllowedEvents) { ++ const Extension* extension = ++ LoadExtension(test_data_dir_.AppendASCII("adblock_private")); ++ ASSERT_TRUE(extension); ++ ++ constexpr char kSetListenersScript[] = R"( ++ var testData = {}; ++ testData.pageAllowedCount = 0; ++ chrome.adblockPrivate.onPageAllowed.addListener(function(e) { ++ if (!e.url.endsWith('test.html')) { ++ return; ++ } ++ testData.pageAllowedCount = testData.pageAllowedCount + 1; ++ }); ++ window.domAutomationController.send(''); ++ )"; ++ ++ constexpr char kReadCountersScript[] = R"( ++ window.domAutomationController.send(testData.pageAllowedCount.toString()); ++ )"; ++ ++ constexpr char kAllowDomainScript[] = R"( ++ chrome.adblockPrivate.addAllowedDomain('example.com'); ++ window.domAutomationController.send(''); ++ )"; ++ ++ GURL test_url = embedded_test_server()->GetURL( ++ "example.com", "/extensions/api_test/adblock_private/test.html"); ++ ++ ExecuteScriptInBackgroundPage(extension->id(), kSetListenersScript); ++ ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url)); ++ ASSERT_EQ( ++ "0", ExecuteScriptInBackgroundPage(extension->id(), kReadCountersScript)); ++ ++ ExecuteScriptInBackgroundPage(extension->id(), kAllowDomainScript); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url)); ++ ASSERT_EQ( ++ "1", ExecuteScriptInBackgroundPage(extension->id(), kReadCountersScript)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiBackgroundPageTest, PageAllowedStats) { ++ const Extension* extension = ++ LoadExtension(test_data_dir_.AppendASCII("adblock_private")); ++ ASSERT_TRUE(extension); ++ ++ constexpr char kReadAllowedStatsScript[] = R"( ++ chrome.adblockPrivate.getSessionAllowedAdsCount(function(sessionStats) { ++ let count = 0; ++ for (const entry of sessionStats) { ++ if (entry.url === 'adblock:custom') { ++ count = entry.count; ++ } ++ } ++ window.domAutomationController.send(count.toString()); ++ }); ++ )"; ++ ++ constexpr char kAllowDomainScript[] = R"( ++ chrome.adblockPrivate.addAllowedDomain('example.com'); ++ window.domAutomationController.send(''); ++ )"; ++ ++ GURL test_url = embedded_test_server()->GetURL( ++ "example.com", "/extensions/api_test/adblock_private/test.html"); ++ int initial_value = std::stoi( ++ ExecuteScriptInBackgroundPage(extension->id(), kReadAllowedStatsScript)); ++ ++ ExecuteScriptInBackgroundPage(extension->id(), kAllowDomainScript); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url)); ++ ++ ASSERT_EQ(initial_value + 1, std::stoi(ExecuteScriptInBackgroundPage( ++ extension->id(), kReadAllowedStatsScript))); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiBackgroundPageTest, PopupEvents) { ++ const Extension* extension = ++ LoadExtension(test_data_dir_.AppendASCII("adblock_private")); ++ ASSERT_TRUE(extension); ++ ++ constexpr char kSetListenersScript[] = R"( ++ var testData = {}; ++ testData.popupBlockedCount = 0; ++ testData.popupAllowedCount = 0; ++ chrome.adblockPrivate.onPopupAllowed.addListener(function(e, blocked) { ++ if (!e.url.endsWith('some-popup.html')) { ++ return; ++ } ++ testData.popupAllowedCount = testData.popupAllowedCount + 1; ++ }); ++ chrome.adblockPrivate.onPopupBlocked.addListener(function(e, blocked) { ++ if (!e.url.endsWith('some-popup.html')) { ++ return; ++ } ++ testData.popupBlockedCount = testData.popupBlockedCount + 1; ++ }); ++ window.domAutomationController.send(''); ++ )"; ++ ++ constexpr char kReadCountersScript[] = R"( ++ window.domAutomationController.send(testData.popupBlockedCount + ++ '-' + testData.popupAllowedCount); ++ )"; ++ ++ constexpr char kBlockPopupScript[] = R"( ++ chrome.adblockPrivate.addCustomFilter('some-popup.html^$popup'); ++ window.domAutomationController.send(''); ++ )"; ++ ++ constexpr char kAllowPopupScript[] = R"( ++ chrome.adblockPrivate.addCustomFilter('@@some-popup.html^$popup'); ++ window.domAutomationController.send(''); ++ )"; ++ ++ GURL test_url = embedded_test_server()->GetURL( ++ "example.com", "/extensions/api_test/adblock_private/test.html"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url)); ++ ++ ExecuteScriptInBackgroundPage(extension->id(), kSetListenersScript); ++ ASSERT_EQ("0-0", ExecuteScriptInBackgroundPage(extension->id(), ++ kReadCountersScript)); ++ ++ ExecuteScriptInBackgroundPage(extension->id(), kBlockPopupScript); ++ ExecuteScript("window.open('some-popup.html');"); ++ ASSERT_EQ("1-0", ExecuteScriptInBackgroundPage(extension->id(), ++ kReadCountersScript)); ++ ++ ExecuteScriptInBackgroundPage(extension->id(), kAllowPopupScript); ++ ExecuteScript("window.open('some-popup.html');"); ++ ASSERT_EQ("1-1", ExecuteScriptInBackgroundPage(extension->id(), ++ kReadCountersScript)); ++} ++ ++IN_PROC_BROWSER_TEST_F(AdblockPrivateApiBackgroundPageTest, PopupStats) { ++ const Extension* extension = ++ LoadExtension(test_data_dir_.AppendASCII("adblock_private")); ++ ASSERT_TRUE(extension); ++ ++ constexpr char kReadAllowedStatsScript[] = R"( ++ chrome.adblockPrivate.getSessionAllowedAdsCount(function(sessionStats) { ++ let count = 0; ++ for (const entry of sessionStats) { ++ if (entry.url === 'adblock:custom') { ++ count = entry.count; ++ } ++ } ++ window.domAutomationController.send(count.toString()); ++ }); ++ )"; ++ ++ constexpr char kReadBlockedStatsScript[] = R"( ++ chrome.adblockPrivate.getSessionBlockedAdsCount(function(sessionStats) { ++ let count = 0; ++ for (const entry of sessionStats) { ++ if (entry.url === 'adblock:custom') { ++ count = entry.count; ++ } ++ } ++ window.domAutomationController.send(count.toString()); ++ }); ++ )"; ++ ++ constexpr char kBlockPopupScript[] = R"( ++ chrome.adblockPrivate.addCustomFilter('some-popup.html^$popup'); ++ window.domAutomationController.send(''); ++ )"; ++ ++ constexpr char kAllowPopupScript[] = R"( ++ chrome.adblockPrivate.addCustomFilter('@@some-popup.html^$popup'); ++ window.domAutomationController.send(''); ++ )"; ++ ++ GURL test_url = embedded_test_server()->GetURL( ++ "example.com", "/extensions/api_test/adblock_private/test.html"); ++ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url)); ++ ++ int initial_allowed_value = std::stoi( ++ ExecuteScriptInBackgroundPage(extension->id(), kReadAllowedStatsScript)); ++ int initial_blocked_value = std::stoi( ++ ExecuteScriptInBackgroundPage(extension->id(), kReadBlockedStatsScript)); ++ ++ ExecuteScriptInBackgroundPage(extension->id(), kBlockPopupScript); ++ ExecuteScript("window.open('some-popup.html');"); ++ ASSERT_EQ(initial_blocked_value + 1, ++ std::stoi(ExecuteScriptInBackgroundPage(extension->id(), ++ kReadBlockedStatsScript))); ++ ++ ExecuteScriptInBackgroundPage(extension->id(), kAllowPopupScript); ++ ExecuteScript("window.open('some-popup.html');"); ++ ASSERT_EQ(initial_allowed_value + 1, ++ std::stoi(ExecuteScriptInBackgroundPage(extension->id(), ++ kReadAllowedStatsScript))); ++} ++ ++} // namespace extensions +diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc +--- a/chrome/browser/extensions/api/settings_private/prefs_util.cc ++++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc +@@ -2,6 +2,10 @@ + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. + ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. ++ + #include "chrome/browser/extensions/api/settings_private/prefs_util.h" + + #include +@@ -25,6 +29,7 @@ + #include "chrome/browser/safe_browsing/generated_safe_browsing_pref.h" + #include "chrome/common/chrome_features.h" + #include "chrome/common/pref_names.h" ++#include "components/adblock/core/common/adblock_prefs.h" + #include "components/autofill/core/common/autofill_prefs.h" + #include "components/bookmarks/common/bookmark_pref_names.h" + #include "components/browsing_data/core/pref_names.h" +@@ -169,6 +174,20 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetAllowlistedKeys() { + return *s_allowlist; + s_allowlist = new PrefsUtil::TypedPrefMap(); + ++ // Adblock settings ++ (*s_allowlist)[adblock::prefs::kEnableAdblock] = ++ settings_api::PrefType::PREF_TYPE_BOOLEAN; ++ (*s_allowlist)[adblock::prefs::kEnableAcceptableAds] = ++ settings_api::PrefType::PREF_TYPE_BOOLEAN; ++ (*s_allowlist)[adblock::prefs::kAdblockSubscriptions] = ++ settings_api::PrefType::PREF_TYPE_LIST; ++ (*s_allowlist)[adblock::prefs::kAdblockCustomSubscriptions] = ++ settings_api::PrefType::PREF_TYPE_LIST; ++ (*s_allowlist)[adblock::prefs::kAdblockAllowedDomains] = ++ settings_api::PrefType::PREF_TYPE_LIST; ++ (*s_allowlist)[adblock::prefs::kAdblockCustomFilters] = ++ settings_api::PrefType::PREF_TYPE_LIST; ++ + // Miscellaneous + (*s_allowlist)[::embedder_support::kAlternateErrorPagesEnabled] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; +diff --git a/chrome/browser/extensions/browser_context_keyed_service_factories.cc b/chrome/browser/extensions/browser_context_keyed_service_factories.cc +--- a/chrome/browser/extensions/browser_context_keyed_service_factories.cc ++++ b/chrome/browser/extensions/browser_context_keyed_service_factories.cc +@@ -1,6 +1,10 @@ + // Copyright 2014 The Chromium Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. ++// ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. + + #include "chrome/browser/extensions/browser_context_keyed_service_factories.h" + +@@ -8,6 +12,7 @@ + #include "build/chromeos_buildflags.h" + #include "chrome/browser/extensions/activity_log/activity_log.h" + #include "chrome/browser/extensions/api/activity_log_private/activity_log_private_api.h" ++#include "chrome/browser/extensions/api/adblock_private/adblock_private_api.h" + #include "chrome/browser/extensions/api/autofill_private/autofill_private_event_router_factory.h" + #include "chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h" + #include "chrome/browser/extensions/api/bookmarks/bookmarks_api.h" +@@ -73,6 +78,7 @@ namespace chrome_extensions { + void EnsureBrowserContextKeyedServiceFactoriesBuilt() { + extensions::ActivityLog::GetFactoryInstance(); + extensions::ActivityLogAPI::GetFactoryInstance(); ++ extensions::AdblockPrivateAPI::GetFactoryInstance(); + extensions::AutofillPrivateEventRouterFactory::GetInstance(); + extensions::BluetoothLowEnergyAPI::GetFactoryInstance(); + extensions::BookmarksAPI::GetFactoryInstance(); +diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc +--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc ++++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_browsertest.cc +@@ -1,6 +1,10 @@ + // Copyright 2017 The Chromium Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. ++// ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. + + #include + #include +@@ -20,6 +24,7 @@ + #include "chrome/browser/ui/browser.h" + #include "chrome/test/base/in_process_browser_test.h" + #include "chrome/test/base/ui_test_utils.h" ++#include "components/adblock/core/features.h" + #include "components/heavy_ad_intervention/heavy_ad_features.h" + #include "components/page_load_metrics/browser/ads_page_load_metrics_test_waiter.h" + #include "components/page_load_metrics/browser/observers/ad_metrics/ad_intervention_browser_test_utils.h" +@@ -1464,7 +1469,7 @@ class AdsPageLoadMetricsObserverResourceBrowserTest + {heavy_ad_intervention::features::kHeavyAdIntervention, {}}, + {heavy_ad_intervention::features::kHeavyAdPrivacyMitigations, + {{"host-threshold", "3"}}}}, +- {}); ++ {adblock::kAdblockPlusFeature}); + } + + ~AdsPageLoadMetricsObserverResourceBrowserTest() override {} +diff --git a/chrome/browser/permissions/notifications_engagement_service_unittest.cc b/chrome/browser/permissions/notifications_engagement_service_unittest.cc +--- a/chrome/browser/permissions/notifications_engagement_service_unittest.cc ++++ b/chrome/browser/permissions/notifications_engagement_service_unittest.cc +@@ -127,8 +127,9 @@ TEST_F(NotificationsEngagementServiceTest, + notifications_engagement_setting.at(1).setting_value); + } + ++// TODO(atokodi) DPD-1495: Re enable when it gets fixed in the upstream + TEST_F(NotificationsEngagementServiceTest, +- RecordNotificationDisplayedAndInteraction) { ++ DISABLED_RecordNotificationDisplayedAndInteraction) { + GURL url1("https://www.google.com/"); + GURL url2("https://www.youtube.com/"); + GURL url3("https://www.permissions.site.com/"); +diff --git a/chrome/browser/preferences/BUILD.gn b/chrome/browser/preferences/BUILD.gn +--- a/chrome/browser/preferences/BUILD.gn ++++ b/chrome/browser/preferences/BUILD.gn +@@ -1,6 +1,10 @@ + # Copyright 2019 The Chromium Authors. All rights reserved. + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. ++# ++# This source code is a part of eyeo Chromium SDK. ++# Use of this source code is governed by the GPLv3 that can be found in the components/adblock/LICENSE file. ++ + + import("//build/config/android/rules.gni") + +@@ -31,6 +35,7 @@ android_library("java") { + java_cpp_strings("java_pref_names_srcjar") { + sources = [ + "//chrome/common/pref_names.cc", ++ "//components/adblock/core/common/adblock_prefs.cc", + "//components/autofill/core/common/autofill_prefs.cc", + "//components/commerce/core/pref_names.cc", + "//components/dom_distiller/core/pref_names.cc", +diff --git a/chrome/browser/prefs/chrome_command_line_pref_store.cc b/chrome/browser/prefs/chrome_command_line_pref_store.cc +--- a/chrome/browser/prefs/chrome_command_line_pref_store.cc ++++ b/chrome/browser/prefs/chrome_command_line_pref_store.cc +@@ -1,6 +1,10 @@ + // Copyright (c) 2012 The Chromium Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. ++// ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. + + #include "chrome/browser/prefs/chrome_command_line_pref_store.h" + +@@ -21,6 +25,8 @@ + #include "build/chromeos_buildflags.h" + #include "chrome/common/chrome_switches.h" + #include "chrome/common/pref_names.h" ++#include "components/adblock/core/common/adblock_prefs.h" ++#include "components/adblock/core/adblock_switches.h" + #include "components/browser_sync/browser_sync_switches.h" + #include "components/language/core/browser/pref_names.h" + #include "components/proxy_config/proxy_config_dictionary.h" +@@ -91,6 +97,10 @@ const CommandLinePrefStore::BooleanSwitchToPreferenceMapEntry + #endif + {switches::kEnableLocalSyncBackend, + syncer::prefs::kEnableLocalSyncBackend, true}, ++ {adblock::switches::kDisableAdblock, adblock::prefs::kEnableAdblock, ++ false}, ++ {adblock::switches::kDisableAcceptableAds, ++ adblock::prefs::kEnableAcceptableAds, false}, + #if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID) + {switches::kUseSystemDefaultPrinter, + prefs::kPrintPreviewUseSystemDefaultPrinter, true}, +diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc +--- a/chrome/browser/prefs/chrome_pref_service_factory.cc ++++ b/chrome/browser/prefs/chrome_pref_service_factory.cc +@@ -1,6 +1,10 @@ + // Copyright (c) 2012 The Chromium Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. ++// ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. + + #include "chrome/browser/prefs/chrome_pref_service_factory.h" + +@@ -38,6 +42,7 @@ + #include "chrome/grit/browser_resources.h" + #include "chrome/grit/chromium_strings.h" + #include "chrome/grit/generated_resources.h" ++#include "components/adblock/core/common/adblock_prefs.h" + #include "components/component_updater/pref_names.h" + #include "components/policy/core/browser/configuration_policy_pref_store.h" + #include "components/pref_registry/pref_registry_syncable.h" +@@ -189,6 +194,12 @@ const prefs::TrackedPreferenceMetadata kTrackedPrefs[] = { + {32, prefs::kMediaCdmOriginData, EnforcementLevel::ENFORCE_ON_LOAD, + PrefTrackingStrategy::ATOMIC, ValueType::IMPERSONAL}, + #endif // BUILDFLAG(IS_WIN) ++ {100, adblock::prefs::kSubscriptionSignatures, ++ EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::SPLIT, ++ ValueType::IMPERSONAL}, ++ {101, adblock::prefs::kLastUsedSchemaVersion, ++ EnforcementLevel::ENFORCE_ON_LOAD, PrefTrackingStrategy::ATOMIC, ++ ValueType::IMPERSONAL}, + + // See note at top, new items added here also need to be added to + // histograms.xml's TrackedPreference enum. +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 +@@ -1,6 +1,10 @@ + // Copyright 2013 The Chromium Authors. All rights reserved. + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. ++// ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. + + #include "chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.h" + +@@ -11,6 +15,14 @@ + #include "build/chromeos_buildflags.h" + #include "chrome/browser/accessibility/page_colors_factory.h" + #include "chrome/browser/accuracy_tips/accuracy_service_factory.h" ++#include "chrome/browser/adblock/adblock_controller_factory.h" ++#include "chrome/browser/adblock/adblock_telemetry_service_factory.h" ++#include "chrome/browser/adblock/resource_classification_runner_factory.h" ++#include "chrome/browser/adblock/session_stats_factory.h" ++#include "chrome/browser/adblock/sitekey_storage_factory.h" ++#include "chrome/browser/adblock/subscription_persistent_metadata_factory.h" ++#include "chrome/browser/adblock/subscription_service_factory.h" ++#include "chrome/browser/adblock/subscription_updater_factory.h" + #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" + #include "chrome/browser/autocomplete/in_memory_url_index_factory.h" + #include "chrome/browser/autocomplete/shortcuts_backend_factory.h" +@@ -136,6 +148,7 @@ + #include "services/network/public/cpp/features.h" + + #if BUILDFLAG(IS_ANDROID) ++#include "chrome/browser/android/adblock/adblock_jni_factory.h" + #include "chrome/browser/android/explore_sites/explore_sites_service_factory.h" + #include "chrome/browser/android/reading_list/reading_list_manager_factory.h" + #include "chrome/browser/android/reading_list/reading_list_notification_service_factory.h" +@@ -377,9 +390,18 @@ void ChromeBrowserMainExtraPartsProfiles:: + #if BUILDFLAG(ENABLE_SESSION_SERVICE) + ExitTypeServiceFactory::GetInstance(); + #endif ++ adblock::AdblockControllerFactory::GetInstance(); ++ adblock::AdblockTelemetryServiceFactory::GetInstance(); ++ adblock::ResourceClassificationRunnerFactory::GetInstance(); ++ adblock::SessionStatsFactory::GetInstance(); ++ adblock::SitekeyStorageFactory::GetInstance(); + #if BUILDFLAG(IS_ANDROID) ++ adblock::AdblockJNIFactory::GetInstance(); + explore_sites::ExploreSitesServiceFactory::GetInstance(); + #endif ++ adblock::SubscriptionPersistentMetadataFactory::GetInstance(); ++ adblock::SubscriptionServiceFactory::GetInstance(); ++ adblock::SubscriptionUpdaterFactory::GetInstance(); + FaviconServiceFactory::GetInstance(); + feature_engagement::TrackerFactory::GetInstance(); + #if !BUILDFLAG(IS_ANDROID) +diff --git a/chrome/browser/profiles/profile_keyed_service_browsertest.cc b/chrome/browser/profiles/profile_keyed_service_browsertest.cc +--- a/chrome/browser/profiles/profile_keyed_service_browsertest.cc ++++ b/chrome/browser/profiles/profile_keyed_service_browsertest.cc +@@ -2,6 +2,10 @@ + // Use of this source code is governed by a BSD-style license that can be + // found in the LICENSE file. + ++// This source code is a part of eyeo Chromium SDK. ++// Use of this source code is governed by the GPLv3 that can be found in the ++// components/adblock/LICENSE file. ++ + #include + + #include "base/test/scoped_feature_list.h" +@@ -428,7 +432,17 @@ IN_PROC_BROWSER_TEST_F(ProfileKeyedServiceBrowserTest, + "WebRtcEventLogManagerKeyedService", + "WebrtcAudioPrivateEventService", + "feedback::FeedbackUploaderChrome", +- "sct_reporting::Factory" ++ "sct_reporting::Factory", ++ ++ // eyeo Chromium SDK services: ++ "AdblockPrivateAPI", ++ "AdblockSubscriptionPersistentMetadata", ++ "AdblockSubscriptionService", ++ "AdblockSubscriptionUpdater", ++ "AdblockTelemetryService", ++ "ResourceClassificationRunner", ++ "SessionStats", ++ "SitekeyStorage", + }; + // clang-format on + +@@ -437,4 +451,319 @@ IN_PROC_BROWSER_TEST_F(ProfileKeyedServiceBrowserTest, + ASSERT_TRUE(system_profile->IsSystemProfile()); + TestKeyedProfileServicesActives(system_profile, system_active_services); + } ++<<<<<<< HEAD + #endif // !BUILDFLAG(IS_CHROMEOS_ASH) ++======= ++ ++IN_PROC_BROWSER_TEST_F(ProfileKeyedServiceBrowserTest, ++ GuestProfileOTR_NeededServices) { ++ // clang-format off ++ std::set guest_otr_active_services { ++#if BUILDFLAG(IS_CHROMEOS_LACROS) ++ "CleanupManagerLacros", ++ "DownloadCoreService", ++#endif // BUILDFLAG(IS_CHROMEOS_LACROS) ++ "AlarmManager", ++ "BackgroundContentsService", ++ "BackgroundSyncService", ++ "BluetoothApiSocketManager", ++ "BluetoothSocketEventDispatcher", ++ "BrowsingDataLifetimeManager", ++ "CookieSettings", ++ "ExtensionSystem", ++ "ExtensionURLLoaderFactory::BrowserContextShutdownNotifierFactory", ++ "FeedbackPrivateAPI", ++ "FileSystemAccessPermissionContext", ++ "GeneratedPrefs", ++ "HeavyAdService", ++ "HidDeviceManager", ++ "HostContentSettingsMap", ++ "LastTabStandingTrackerKeyedService", ++ "MediaRouterUIService", ++ "NotificationDisplayService", ++ "OptimizationGuideKeyedService", ++ "PlatformNotificationService", ++ "PrefWatcher", ++ "PrivacySandboxSettings", ++ "ProcessManager", ++ "ProfileNetworkContextService", ++ "RealtimeReportingClient", ++ "RendererUpdater", ++ "ResumableTCPServerSocketManager", ++ "ResumableTCPSocketManager", ++ "ResumableUDPSocketManager", ++ "RulesRegistryService", ++ "SafeBrowsingPrivateEventRouter", ++ "SerialConnectionManager", ++ "SettingsPrivateEventRouter", ++ "SiteDataCacheFacadeFactory", ++ "SiteEngagementService", ++ "SocketManager", ++ "StorageNotificationService", ++ "TCPServerSocketEventDispatcher", ++ "TCPSocketEventDispatcher", ++ "TabGroupsEventRouter", ++ "ToolbarActionsModel", ++ "UDPSocketEventDispatcher", ++ "UkmBackgroundRecorderService", ++ "UsbDeviceManager", ++ "UsbDeviceResourceManager", ++ "sct_reporting::Factory" ++ }; ++ // clang-format on ++ ++ Profile* guest_profile = ++ CreateProfileAndWaitForAllTaks(ProfileManager::GetGuestProfilePath()); ++ ASSERT_TRUE(guest_profile->HasAnyOffTheRecordProfile()); ++ Profile* guest_profile_otr = guest_profile->GetPrimaryOTRProfile(false); ++ ASSERT_TRUE(guest_profile_otr->IsOffTheRecord()); ++ ASSERT_TRUE(guest_profile_otr->IsGuestSession()); ++ TestKeyedProfileServicesActives(guest_profile_otr, guest_otr_active_services); ++} ++ ++IN_PROC_BROWSER_TEST_F(ProfileKeyedServiceBrowserTest, ++ GuestProfileParent_NeededServices) { ++ // clang-format off ++ std::set guest_active_services { ++#if BUILDFLAG(IS_CHROMEOS_LACROS) ++ "ChildAccountService", ++ "CleanupManagerLacros", ++ "ClipboardAPI", ++ "ExternalLogoutRequestEventHandler", ++ "ManualTestHeartbeatEvent", ++ "SessionStateChangedEventDispatcher", ++ "SupervisedUserService", ++#else // !BUILDFLAG(IS_CHROMEOS_LACROS) ++ "SystemIndicatorManager", ++ "WebAppAdjustments", ++ "WebAppProvider", ++#endif ++#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) ++ "SpellcheckService", ++#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN) ++ "AboutSigninInternals", ++ "AboutThisSiteServiceFactory", ++ "AccessibilityLabelsService", ++ "AccountInvestigator", ++ "AccountPasswordStore", ++ "AccountReconcilor", ++ "ActivityLog", ++ "ActivityLogPrivateAPI", ++ "AdaptiveQuietNotificationPermissionUiEnabler", ++ "AdvancedProtectionStatusManager", ++ "AffiliationService", ++ "AlarmManager", ++ "AnnouncementNotificationService", ++ "AppLifetimeMonitor", ++ "AppLoadService", ++ "AppRestoreService", ++ "AppServiceProxy", ++ "AppShortcutManager", ++ "AppTerminationObserver", ++ "AppWindowRegistry", ++ "AudioAPI", ++ "AutofillImageFetcher", ++ "AutofillPrivateEventRouter", ++ "AutofillStrikeDatabase", ++ "BackgroundContentsService", ++ "BackgroundFetchService", ++ "BackgroundSyncService", ++ "Blocklist", ++ "BluetoothAPI", ++ "BluetoothApiSocketManager", ++ "BluetoothLowEnergyAPI", ++ "BluetoothPrivateAPI", ++ "BluetoothSocketEventDispatcher", ++ "BookmarkManagerPrivateAPI", ++ "BookmarkModel", ++ "BookmarkSyncServiceFactory", ++ "BookmarkUndoService", ++ "BookmarksAPI", ++ "BookmarksApiWatcher", ++ "BrailleDisplayPrivateAPI", ++ "BreadcrumbManagerService", ++ "BrowsingTopicsService", ++ "ChromeSigninClient", ++ "CommandService", ++ "ConsentAuditor", ++ "ContentIndexProvider", ++ "ContentSettingsService", ++ "CookieSettings", ++ "CookiesAPI", ++ "CredentialsCleanerRunner", ++ "DeveloperPrivateAPI", ++ "DeviceInfoSyncService", ++ "DownloadCoreService", ++ "EventRouter", ++ "ExtensionActionAPI", ++ "ExtensionActionManager", ++ "ExtensionCommandsGlobalRegistry", ++ "ExtensionGCMAppHandler", ++ "ExtensionGarbageCollector", ++ "ExtensionHostRegistry", ++ "ExtensionManagement", ++ "ExtensionPrefValueMap", ++ "ExtensionPrefs", ++ "ExtensionRegistry", ++ "ExtensionSyncService", ++ "ExtensionSystem", ++ "ExtensionSystemShared", ++ "ExtensionURLLoaderFactory::BrowserContextShutdownNotifierFactory", ++ "ExtensionWebUIOverrideRegistrar", ++ "FaviconService", ++ "FeedbackPrivateAPI", ++ "FileSystemAccessPermissionContext", ++ "FontPrefChangeNotifier", ++ "FontSettingsAPI", ++ "GAIAInfoUpdateService", ++ "GCMProfileService", ++ "GeneratedPrefs", ++ "HeavyAdService", ++ "HidDeviceManager", ++ "HistoryAPI", ++ "HistoryService", ++ "HostContentSettingsMap", ++ "HttpEngagementKeyService", ++ "IdentityAPI", ++ "IdentityManager", ++ "IdleManager", ++ "InstallStageTracker", ++ "InstallTracker", ++ "InstallVerifier", ++ "InstanceIDProfileService", ++ "InvalidationService", ++ "LanguageSettingsPrivateDelegate", ++ "LastTabStandingTrackerKeyedService", ++ "LazyBackgroundTaskQueue", ++ "LiveCaptionController", ++ "LoginUIServiceFactory", ++ "MDnsAPI", ++ "ManagedBookmarkService", ++ "ManagedConfigurationAPI", ++ "ManagementAPI", ++ "MediaRouter", ++ "MediaRouterUIService", ++ "MenuManager", ++ "ModelTypeStoreService", ++ "NavigationPredictorKeyedService", ++ "NetworkingPrivateEventRouter", ++ "NotificationDisplayService", ++ "NotifierStateTracker", ++ "OmniboxAPI", ++ "OptimizationGuideKeyedService", ++ "PageContentAnnotationsService", ++ "PasswordStore", ++ "PasswordsPrivateEventRouter", ++ "PermissionHelper", ++ "PermissionsManager", ++ "PermissionsUpdaterShutdownFactory", ++ "PersonalDataManager", ++ "PinnedTabService", ++ "PlatformNotificationService", ++ "PluginManager", ++ "PluginPrefs", ++ "PowerBookmarkService", ++ "PrefMetricsService", ++ "PrefWatcher", ++ "PreferenceAPI", ++ "PrimaryAccountPolicyManager", ++ #if BUILDFLAG(IS_CHROMEOS) && defined(USE_CUPS) ++ "PrintingMetricsService", ++ #endif // BUILDFLAG(IS_CHROMEOS) && defined(USE_CUPS) ++ "PrivacyMetricsService", ++ "PrivacySandboxService", ++ "PrivacySandboxSettings", ++ "ProcessManager", ++ "ProcessMap", ++ "ProcessesAPI", ++ "ProfileNetworkContextService", ++ "ProfileThemeUpdateServiceFactory", ++ "ProtocolHandlerRegistry", ++ "ReadingListModel", ++ "RealtimeReportingClient", ++ "RendererStartupHelper", ++ "RendererUpdater", ++ "ResumableTCPServerSocketManager", ++ "ResumableTCPSocketManager", ++ "ResumableUDPSocketManager", ++ "RulesMonitorService", ++ "RulesRegistryService", ++ "RuntimeAPI", ++ "SafeBrowsingMetricsCollector", ++ "SafeBrowsingNetworkContextService", ++ "SafeBrowsingPrivateEventRouter", ++ "SafeBrowsingTailoredSecurityService", ++ "SecurityEventRecorder", ++ "SendTabToSelfClientService", ++ "SendTabToSelfSyncService", ++ "SerialConnectionManager", ++ "SessionDataService", ++ "SessionProtoDBFactory", ++ "SessionSyncService", ++ "SessionsAPI", ++ "SettingsOverridesAPI", ++ "SettingsPrivateEventRouter", ++ "SharingMessageBridge", ++ "SharingService", ++ "ShoppingService", ++ "SidePanelService", ++ "SigninErrorController", ++ "SigninManager", ++ "SigninProfileAttributesUpdater", ++ "SiteDataCacheFacadeFactory", ++ "SiteEngagementService", ++ "SocketManager", ++ "StorageFrontend", ++ "StorageNotificationService", ++ "SyncInvalidationsService", ++ "SyncService", ++ "SyncSessionsWebContentsRouter", ++ "SystemInfoAPI", ++ "TCPServerSocketEventDispatcher", ++ "TCPSocketEventDispatcher", ++ "TabGroupsEventRouter", ++ "TabsWindowsAPI", ++ "TemplateURLServiceFactory", ++ "ThemeService", ++ "ToolbarActionsModel", ++ "TranslateRanker", ++ "TriggeredProfileResetter", ++ "TtsAPI", ++ "UDPSocketEventDispatcher", ++ "UkmBackgroundRecorderService", ++ "UnifiedConsentService", ++ "UsbDeviceManager", ++ "UsbDeviceResourceManager", ++ "UserCloudPolicyInvalidator", ++ "UserEventService", ++ "UserPolicySigninService", ++ "WarningBadgeService", ++ "WarningService", ++ "WebAuthenticationProxyAPI", ++ "WebDataService", ++ "WebNavigationAPI", ++ "WebRequestAPI", ++ "WebRtcEventLogManagerKeyedService", ++ "WebrtcAudioPrivateEventService", ++ "feedback::FeedbackUploaderChrome", ++ "sct_reporting::Factory", ++ ++ // eyeo Chromium SDK services: ++ "AdblockPrivateAPI", ++ "AdblockSubscriptionPersistentMetadata", ++ "AdblockSubscriptionService", ++ "AdblockSubscriptionUpdater", ++ "AdblockTelemetryService", ++ "ResourceClassificationRunner", ++ "SessionStats", ++ "SitekeyStorage", ++ }; ++ // clang-format on ++ ++ Profile* guest_profile = ++ CreateProfileAndWaitForAllTaks(ProfileManager::GetGuestProfilePath()); ++ ASSERT_FALSE(guest_profile->IsOffTheRecord()); ++ ASSERT_TRUE(guest_profile->IsGuestSession()); ++ TestKeyedProfileServicesActives(guest_profile, guest_active_services); ++} ++>>>>>>> 54b2a67d3c457... Squashed commits +diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn +--- a/chrome/browser/resources/settings/BUILD.gn ++++ b/chrome/browser/resources/settings/BUILD.gn +@@ -2,6 +2,10 @@ + # Use of this source code is governed by a BSD-style license that can be + # found in the LICENSE file. + ++# This source code is a part of eyeo Chromium SDK. ++# Use of this source code is governed by the GPLv3 that can be found in the ++# components/adblock/LICENSE file. ++ + import("//build/config/chromeos/ui_mode.gni") + import("//chrome/browser/resources/tools/build_webui.gni") + import("//chrome/common/features.gni") +@@ -109,6 +113,7 @@ build_webui("build") { + "a11y_page/a11y_page.ts", + "a11y_page/live_caption_section.ts", + "about_page/about_page.ts", ++ "adblock_page/adblock_page.ts", + "appearance_page/appearance_fonts_page.ts", + "appearance_page/appearance_page.ts", + "appearance_page/home_url_input.ts", +diff --git a/chrome/browser/resources/settings/adblock_page/adblock_page.html b/chrome/browser/resources/settings/adblock_page/adblock_page.html +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/resources/settings/adblock_page/adblock_page.html +@@ -0,0 +1,186 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++
++
++ ++
++ Recommended Subscriptions ++
++
++ ++
++ ++
++
++ ++
++
++
++
++ ++
++ Allowed Domains ++
++
++ ++
++ ++
++
++ ++
++
++ ++ ++ Add ++ ++ ++
++
++
++
++
++
++ ++
++ Custom Subscriptions ++
++
++ ++
++ ++
++
++ ++
++
++ ++ ++ Add ++ ++ ++
++
++
++
++
++
++ ++
++ Custom Filters ++
++
++ ++
++ ++
++
++ ++
++
++ ++ ++ Add ++ ++ ++
++
++
++
++
++ ++
+diff --git a/chrome/browser/resources/settings/adblock_page/adblock_page.ts b/chrome/browser/resources/settings/adblock_page/adblock_page.ts +new file mode 100644 +--- /dev/null ++++ b/chrome/browser/resources/settings/adblock_page/adblock_page.ts +@@ -0,0 +1,317 @@ ++/* ++ * 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 . ++ */ ++import 'chrome://resources/cr_elements/cr_button/cr_button.js'; ++import 'chrome://resources/cr_elements/cr_shared_style.css.js'; ++import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js'; ++import 'chrome://resources/polymer/v3_0/iron-flex-layout/iron-flex-layout-classes.js'; ++import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; ++import '../controls/controlled_button.js'; ++import '../controls/settings_toggle_button.js'; ++import '../settings_shared.css.js'; ++ ++ ++import { I18nMixin } from 'chrome://resources/js/i18n_mixin.js'; ++import { BaseMixin } from '../base_mixin.js'; ++import { html, PolymerElement } from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; ++import { PrefsMixin } from '../prefs/prefs_mixin.js'; ++import { CrSettingsPrefs } from '../prefs/prefs_types.js'; ++import { CrCheckboxElement } from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.js'; ++import { getTemplate } from './adblock_page.html.js'; ++ ++const SettingsAdblockPageElementBase = ++ I18nMixin(PrefsMixin(BaseMixin((PolymerElement)))); ++ ++export class SettingsAdblockPageElement extends ++ SettingsAdblockPageElementBase { ++ static get is() { ++ return 'settings-adblock-page'; ++ } ++ ++ static get template() { ++ return getTemplate(); ++ } ++ ++ private syncSubscriptions() { ++ let prefSubscriptions = this.getPref("adblock.subscriptions").value; ++ this.subscriptions.forEach((subscription, i) => { ++ if (prefSubscriptions.includes(subscription['url'])) { ++ this.set("subscriptions." + i.toString() + ".enabled", true) ++ } else { ++ this.set("subscriptions." + i.toString() + ".enabled", false) ++ } ++ }) ++ } ++ ++ private syncCustomSubscriptions() { ++ let prefCustomSubscriptions = this.getPref("adblock.custom_subscriptions").value; ++ this.customSubscriptions = []; ++ prefCustomSubscriptions.forEach((subscription: string) => { ++ this.customSubscriptions.push(subscription); ++ }) ++ } ++ ++ private syncCustomFilters() { ++ let prefCustomFilters = this.getPref("adblock.custom_filters").value; ++ this.customFilters = []; ++ prefCustomFilters.forEach((filter: string) => { ++ this.customFilters.push(filter); ++ }) ++ } ++ ++ private syncAllowedDomains() { ++ let prefAllowedDomains = this.getPref("adblock.allowed_domains").value; ++ this.allowedDomains = []; ++ prefAllowedDomains.forEach((subscription: string) => { ++ this.allowedDomains.push(subscription); ++ }) ++ } ++ ++ public override ready() { ++ super.ready(); ++ // when prefs are ready ++ CrSettingsPrefs.initialized.then(() => { ++ this.syncSubscriptions(); ++ this.syncCustomSubscriptions(); ++ this.syncCustomFilters(); ++ this.syncAllowedDomains(); ++ }); ++ } ++ ++ // input fields updated by html ++ public customSubscriptionInput: string; ++ public customFilterInput: string; ++ public allowedDomainInput: string; ++ ++ // models that will fill templates lists in html ++ public customSubscriptions: Array = []; ++ public customFilters: Array = []; ++ public allowedDomains: Array = []; ++ public subscriptions = [ ++ { ++ title: "ABPindo+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/abpindo+easylist.txt" ++ }, ++ { ++ title: "ABPVN List+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/abpvn+easylist.txt" ++ }, ++ { ++ title: "Bulgarian list+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/bulgarian_list+easylist.txt" ++ }, ++ { ++ title: "Dandelion Sprout's Nordic Filters+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/dandelion_sprouts_nordic_filters+easylist.txt" ++ }, ++ { ++ title: "EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/easylist.txt" ++ }, ++ { ++ title: "EasyList China+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt" ++ }, ++ { ++ title: "EasyList Czech and Slovak+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/easylistczechslovak+easylist.txt" ++ }, ++ { ++ title: "EasyList Dutch+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/easylistdutch+easylist.txt" ++ }, ++ { ++ title: "EasyList Germany+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/easylistgermany+easylist.txt" ++ }, ++ { ++ title: "EasyList Hebrew+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/israellist+easylist.txt" ++ }, ++ { ++ title: "EasyList Italy+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/easylistitaly+easylist.txt" ++ }, ++ { ++ title: "EasyList Lithuania+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/easylistlithuania+easylist.txt" ++ }, ++ { ++ title: "EasyList Polish+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/easylistpolish+easylist.txt" ++ }, ++ { ++ title: "EasyList Portuguese+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/easylistportuguese+easylist.txt" ++ }, ++ { ++ title: "EasyList Spanish+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/easylistspanish+easylist.txt" ++ }, ++ { ++ title: "IndianList+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/indianlist+easylist.txt" ++ }, ++ { ++ title: "KoreanList+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/koreanlist+easylist.txt" ++ }, ++ { ++ title: "Latvian List+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/latvianlist+easylist.txt" ++ }, ++ { ++ title: "Liste AR+Liste FR+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/liste_ar+liste_fr+easylist.txt" ++ }, ++ { ++ title: "Liste FR+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/liste_fr+easylist.txt" ++ }, ++ { ++ title: "ROList+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/rolist+easylist.txt" ++ }, ++ { ++ title: "RuAdList+EasyList", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/ruadlist+easylist.txt" ++ }, ++ { ++ title: "ABP filters", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/abp-filters-anti-cv.txt" ++ }, ++ { ++ title: "I don't care about cookies", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/i_dont_care_about_cookies.txt" ++ }, ++ { ++ title: "Fanboy's Notifications Blocking List", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/fanboy-notifications.txt" ++ }, ++ { ++ title: "EasyPrivacy", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/easyprivacy.txt" ++ }, ++ { ++ title: "Fanboy's Social Blocking List", ++ enabled: false, ++ url: "https://easylist-downloads.adblockplus.org/fanboy-social.txt" ++ } ++ ]; ++ ++ private cleanUrl(url: string) : string { ++ let cleanedUrl : string = ""; ++ try { ++ cleanedUrl = new URL(url).host; ++ } catch (err) { ++ try { ++ // one last try by adding schema ++ cleanedUrl = new URL("https://" + url).host; ++ } ++ catch (err) { ++ console.log("malformed url " + url); ++ } ++ } ++ return cleanedUrl; ++ } ++ ++ private selectRecommendedSubscription(e: Event) { ++ const url = ((e.target as CrCheckboxElement).id); ++ const enabled = ((e.target as CrCheckboxElement).checked); ++ if (enabled) { ++ this.appendPrefListItem("adblock.subscriptions", url); ++ } else { ++ this.deletePrefListItem("adblock.subscriptions", url); ++ } ++ } ++ ++ private removeCustomFilter(e: Event) { ++ const filter = ((e.target as HTMLElement).id); ++ this.deletePrefListItem("adblock.custom_filters", filter); ++ const i = this.customFilters.indexOf(filter); ++ this.splice('customFilters', i, 1); ++ } ++ ++ private addCustomFilter() { ++ if (this.customFilterInput == undefined) return; ++ this.appendPrefListItem("adblock.custom_filters", this.customFilterInput); ++ this.push('customFilters', this.customFilterInput); ++ } ++ ++ private removeAllowedDomain(e: Event) { ++ const allowedDomain = ((e.target as HTMLElement).id); ++ this.deletePrefListItem("adblock.allowed_domains", allowedDomain); ++ const i = this.allowedDomains.indexOf(allowedDomain); ++ this.splice('allowedDomains', i, 1); ++ } ++ ++ private addAllowedDomain() { ++ if (this.allowedDomainInput == undefined) return; ++ const cleanedUrl = this.cleanUrl(this.allowedDomainInput); ++ if (cleanedUrl == "") return; ++ this.appendPrefListItem("adblock.allowed_domains", cleanedUrl); ++ this.push('allowedDomains', cleanedUrl); ++ } ++ ++ private removeCustomSubscription(e: Event) { ++ const subscription = ((e.target as HTMLElement).id); ++ this.deletePrefListItem("adblock.custom_subscriptions", subscription); ++ const i = this.customSubscriptions.indexOf(subscription); ++ this.splice('customSubscriptions', i, 1); ++ } ++ ++ private addCustomSubscription() { ++ if (this.customSubscriptionInput == undefined) return; ++ this.appendPrefListItem("adblock.custom_subscriptions", this.customSubscriptionInput); ++ this.push('customSubscriptions', this.customSubscriptionInput); ++ } ++} ++ ++ ++declare global { ++ interface HTMLElementTagNameMap { ++ 'settings-adblock-page': SettingsAdblockPageElement; ++ } ++} ++ ++customElements.define( ++ SettingsAdblockPageElement.is, SettingsAdblockPageElement); +diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html +--- a/chrome/browser/resources/settings/basic_page/basic_page.html ++++ b/chrome/browser/resources/settings/basic_page/basic_page.html +@@ -24,6 +24,13 @@ + + + ++ +