5210 lines
214 KiB
Diff
5210 lines
214 KiB
Diff
From: Your Name <you@example.com>
|
|
Date: Thu, 29 Sep 2022 11:27:35 +0000
|
|
Subject: Eyeo Adblock Remove
|
|
|
|
---
|
|
.../android/java/res/xml/main_preferences.xml | 11 +-
|
|
chrome/browser/BUILD.gn | 2 -
|
|
.../adblock/adblock_content_browser_client.cc | 17 -
|
|
.../adblock/adblock_controller_factory.cc | 3 +-
|
|
.../adblock_telemetry_service_factory.cc | 138 -
|
|
.../adblock_telemetry_service_factory.h | 56 -
|
|
.../adblock/subscription_service_factory.cc | 2 +-
|
|
...hrome_browser_main_extra_parts_profiles.cc | 2 -
|
|
chrome/browser/ui/tab_helpers.cc | 2 +
|
|
chrome/test/BUILD.gn | 1 -
|
|
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/browser/BUILD.gn | 14 -
|
|
components/adblock/core/BUILD.gn | 45 -
|
|
.../activeping_telemetry_topic_provider.cc | 241 --
|
|
.../activeping_telemetry_topic_provider.h | 83 -
|
|
.../adblock/core/adblock_controller_impl.cc | 7 +-
|
|
components/adblock/core/adblock_switches.cc | 1 -
|
|
components/adblock/core/adblock_switches.h | 1 -
|
|
.../adblock/core/adblock_telemetry_service.cc | 244 --
|
|
.../adblock/core/adblock_telemetry_service.h | 106 -
|
|
.../adblock/core/common/adblock_constants.cc | 2 -
|
|
.../adblock/core/common/adblock_constants.h | 1 -
|
|
.../adblock/core/common/adblock_prefs.cc | 44 +-
|
|
.../adblock/core/common/adblock_utils.cc | 23 -
|
|
.../adblock/core/converter/parser/metadata.cc | 6 +-
|
|
.../adblock/core/sitekey_storage_impl.cc | 6 +
|
|
...filtering_configuration_maintainer_impl.cc | 10 -
|
|
.../filtering_configuration_maintainer_impl.h | 1 -
|
|
.../ongoing_subscription_request_impl.cc | 27 +-
|
|
.../preloaded_subscription_provider_impl.cc | 4 +-
|
|
.../core/subscription/subscription_config.cc | 8 +-
|
|
.../subscription_downloader_impl.cc | 15 +-
|
|
.../subscription_persistent_storage_impl.cc | 4 +
|
|
.../subscription/subscription_service_impl.cc | 2 +-
|
|
.../subscription/subscription_updater_impl.cc | 8 +-
|
|
.../subscription_validator_impl.cc | 4 +-
|
|
components/adblock/features.gni | 44 -
|
|
components/resources/BUILD.gn | 1 -
|
|
components/resources/adblock_resources.grdp | 3 -
|
|
components/resources/adblocking/.gitignore | 2 +-
|
|
components/resources/adblocking/BUILD.gn | 30 +-
|
|
.../snippets/dist/isolated-first.jst | 62 +
|
|
.../snippets/dist/isolated-first.source.jst | 3126 +++++++++++++++++
|
|
.../blink/renderer/core/css/style_engine.cc | 8 +
|
|
.../blink/renderer/core/css/style_engine.h | 1 +
|
|
.../renderer/core/exported/web_document.cc | 13 +-
|
|
50 files changed, 3290 insertions(+), 1158 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/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/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
|
|
@@ -1,13 +1,4 @@
|
|
<?xml version="1.0" encoding="utf-8"?>
|
|
-<!--
|
|
-Copyright 2015 The Chromium Authors
|
|
-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.
|
|
--->
|
|
-
|
|
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
android:orderingFromXml="false">
|
|
@@ -83,7 +74,7 @@ Use of this source code is governed by the GPLv3 that can be found in the compon
|
|
android:title="@string/prefs_accessibility"/>
|
|
<Preference
|
|
android:fragment="org.chromium.components.adblock.settings.AdblockSettingsFragment"
|
|
- android:key="adblock"
|
|
+ android:key="eyeo_adblock"
|
|
android:order="18"
|
|
android:title="@string/adblock_settings_title" />
|
|
<Preference
|
|
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
|
|
--- a/chrome/browser/BUILD.gn
|
|
+++ b/chrome/browser/BUILD.gn
|
|
@@ -159,8 +159,6 @@ static_library("browser") {
|
|
"adblock/adblock_content_browser_client.h",
|
|
"adblock/adblock_controller_factory.cc",
|
|
"adblock/adblock_controller_factory.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",
|
|
diff --git a/chrome/browser/adblock/adblock_content_browser_client.cc b/chrome/browser/adblock/adblock_content_browser_client.cc
|
|
--- a/chrome/browser/adblock/adblock_content_browser_client.cc
|
|
+++ b/chrome/browser/adblock/adblock_content_browser_client.cc
|
|
@@ -104,23 +104,6 @@ class AdblockContextData : public base::SupportsUserData::Data {
|
|
adblock::SitekeyStorageFactory::GetForBrowserContext(browser_context),
|
|
adblock::ContentSecurityPolicyInjectorFactory::GetForBrowserContext(
|
|
browser_context)};
|
|
-#ifdef EYEO_INTERCEPT_DEBUG_URL
|
|
- if (use_test_loader) {
|
|
- auto proxy = std::make_unique<adblock::AdblockURLLoaderFactoryForTest>(
|
|
- std::move(config),
|
|
- content::GlobalRenderFrameHostId(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<adblock::AdblockURLLoaderFactory>(
|
|
std::move(config),
|
|
content::GlobalRenderFrameHostId(render_process_id,
|
|
diff --git a/chrome/browser/adblock/adblock_controller_factory.cc b/chrome/browser/adblock/adblock_controller_factory.cc
|
|
--- a/chrome/browser/adblock/adblock_controller_factory.cc
|
|
+++ b/chrome/browser/adblock/adblock_controller_factory.cc
|
|
@@ -63,8 +63,7 @@ KeyedService* AdblockControllerFactory::BuildServiceInstanceFor(
|
|
auto adblock_filtering_configuration =
|
|
std::make_unique<PersistentFilteringConfiguration>(prefs, "adblock");
|
|
|
|
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
|
- adblock::switches::kDisableAcceptableAds)) {
|
|
+ if ((true)) {
|
|
adblock_filtering_configuration->RemoveFilterList(AcceptableAdsUrl());
|
|
}
|
|
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
|
|
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,138 +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 <http://www.gnu.org/licenses/>.
|
|
- */
|
|
-
|
|
-#include "chrome/browser/adblock/adblock_telemetry_service_factory.h"
|
|
-
|
|
-#include <memory>
|
|
-
|
|
-#include "base/no_destructor.h"
|
|
-#include "chrome/browser/adblock/adblock_controller_factory.h"
|
|
-#include "chrome/browser/adblock/subscription_service_factory.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/adblock/core/configuration/filtering_configuration.h"
|
|
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
|
|
-#include "content/public/browser/storage_partition.h"
|
|
-
|
|
-namespace adblock {
|
|
-namespace {
|
|
-std::optional<base::TimeDelta> g_check_interval_for_testing;
|
|
-std::optional<base::TimeDelta> g_initial_delay_for_testing;
|
|
-constexpr base::StringPiece kAdblockFilteringConfigurationName = "adblock";
|
|
-
|
|
-base::TimeDelta GetInitialDelay() {
|
|
- static base::TimeDelta kInitialDelay =
|
|
- g_initial_delay_for_testing ? g_initial_delay_for_testing.value()
|
|
- : base::Seconds(30);
|
|
- return kInitialDelay;
|
|
-}
|
|
-
|
|
-base::TimeDelta GetCheckInterval() {
|
|
- static base::TimeDelta kCheckInterval =
|
|
- g_check_interval_for_testing ? g_check_interval_for_testing.value()
|
|
- : base::Minutes(5);
|
|
- return kCheckInterval;
|
|
-}
|
|
-
|
|
-FilteringConfiguration* GetAdblockFilteringConfiguration(
|
|
- content::BrowserContext* context) {
|
|
- auto filtering_configurations =
|
|
- SubscriptionServiceFactory::GetForBrowserContext(context)
|
|
- ->GetInstalledFilteringConfigurations();
|
|
- const auto it = base::ranges::find(filtering_configurations,
|
|
- kAdblockFilteringConfigurationName,
|
|
- &FilteringConfiguration::GetName);
|
|
- DCHECK(it != filtering_configurations.end());
|
|
- return *it;
|
|
-}
|
|
-} // namespace
|
|
-
|
|
-// static
|
|
-AdblockTelemetryService* AdblockTelemetryServiceFactory::GetForProfile(
|
|
- Profile* profile) {
|
|
- return static_cast<AdblockTelemetryService*>(
|
|
- GetInstance()->GetServiceForBrowserContext(profile, true));
|
|
-}
|
|
-// static
|
|
-AdblockTelemetryServiceFactory* AdblockTelemetryServiceFactory::GetInstance() {
|
|
- static base::NoDestructor<AdblockTelemetryServiceFactory> instance;
|
|
- return instance.get();
|
|
-}
|
|
-
|
|
-AdblockTelemetryServiceFactory::AdblockTelemetryServiceFactory()
|
|
- : BrowserContextKeyedServiceFactory(
|
|
- "AdblockTelemetryService",
|
|
- BrowserContextDependencyManager::GetInstance()) {
|
|
- // AdblockController creates Adblock Filtering Configuration required by
|
|
- // AdblockTelemetryService
|
|
- DependsOn(AdblockControllerFactory::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<network::SharedURLLoaderFactory> url_loader_factory =
|
|
- context->GetDefaultStoragePartition()
|
|
- ->GetURLLoaderFactoryForBrowserProcess();
|
|
- auto* prefs = Profile::FromBrowserContext(context)->GetPrefs();
|
|
- auto service = std::make_unique<AdblockTelemetryService>(
|
|
- GetAdblockFilteringConfiguration(context), url_loader_factory,
|
|
- GetInitialDelay(), GetCheckInterval());
|
|
- service->AddTopicProvider(std::make_unique<ActivepingTelemetryTopicProvider>(
|
|
- utils::GetAppInfo(), prefs,
|
|
- AdblockControllerFactory::GetForBrowserContext(context),
|
|
- 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;
|
|
-}
|
|
-
|
|
-void AdblockTelemetryServiceFactory::SetCheckAndDelayIntervalsForTesting(
|
|
- base::TimeDelta check_interval,
|
|
- base::TimeDelta initial_delay) {
|
|
- g_check_interval_for_testing = check_interval;
|
|
- g_initial_delay_for_testing = initial_delay;
|
|
-}
|
|
-
|
|
-} // 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,56 +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 <http://www.gnu.org/licenses/>.
|
|
- */
|
|
-
|
|
-#ifndef CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_
|
|
-#define CHROME_BROWSER_ADBLOCK_ADBLOCK_TELEMETRY_SERVICE_FACTORY_H_
|
|
-
|
|
-#include "base/no_destructor.h"
|
|
-#include "base/time/time.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();
|
|
-
|
|
- // Sets the initial delay and interval checks required for browser tests.
|
|
- // Must be called before BuildServiceInstanceFor().
|
|
- void SetCheckAndDelayIntervalsForTesting(base::TimeDelta check_interval,
|
|
- base::TimeDelta initial_delay);
|
|
-
|
|
- private:
|
|
- friend class base::NoDestructor<AdblockTelemetryServiceFactory>;
|
|
- 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_service_factory.cc b/chrome/browser/adblock/subscription_service_factory.cc
|
|
--- a/chrome/browser/adblock/subscription_service_factory.cc
|
|
+++ b/chrome/browser/adblock/subscription_service_factory.cc
|
|
@@ -66,7 +66,7 @@ base::TimeDelta GetUpdateCheckInterval() {
|
|
static base::TimeDelta kCheckInterval =
|
|
g_update_check_interval_for_testing
|
|
? g_update_check_interval_for_testing.value()
|
|
- : base::Hours(1);
|
|
+ : base::Hours(24);
|
|
return kCheckInterval;
|
|
}
|
|
|
|
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/accessibility_labels_service_factory.h"
|
|
#include "chrome/browser/accessibility/page_colors_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"
|
|
@@ -584,7 +583,6 @@ void ChromeBrowserMainExtraPartsProfiles::
|
|
ExitTypeServiceFactory::GetInstance();
|
|
#endif
|
|
adblock::AdblockControllerFactory::GetInstance();
|
|
- adblock::AdblockTelemetryServiceFactory::GetInstance();
|
|
adblock::ResourceClassificationRunnerFactory::GetInstance();
|
|
adblock::SessionStatsFactory::GetInstance();
|
|
adblock::SitekeyStorageFactory::GetInstance();
|
|
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
|
|
--- a/chrome/browser/ui/tab_helpers.cc
|
|
+++ b/chrome/browser/ui/tab_helpers.cc
|
|
@@ -325,6 +325,8 @@ void TabHelpers::AttachTabHelpers(WebContents* web_contents) {
|
|
}
|
|
#endif
|
|
|
|
+ adblock::AdblockControllerFactory::GetForBrowserContext(
|
|
+ web_contents->GetBrowserContext());
|
|
AdblockWebContentObserver::CreateForWebContents(
|
|
web_contents,
|
|
adblock::SubscriptionServiceFactory::GetForBrowserContext(
|
|
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
|
|
--- a/chrome/test/BUILD.gn
|
|
+++ b/chrome/test/BUILD.gn
|
|
@@ -26,7 +26,6 @@ import("//chrome/test/base/js2gtest.gni")
|
|
import("//chrome/test/include_js_tests.gni")
|
|
import("//chrome/version.gni")
|
|
import("//chromeos/ash/components/assistant/assistant.gni")
|
|
-import("//components/adblock/features.gni")
|
|
import("//components/captive_portal/core/features.gni")
|
|
import("//components/feed/features.gni")
|
|
import("//components/gwp_asan/buildflags/buildflags.gni")
|
|
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
|
|
@@ -95,7 +95,7 @@ android_resources("java_resources") {
|
|
"java/res/layout/adblock_custom_item_settings.xml",
|
|
"java/res/layout/adblock_filter_lists_list_item.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" />
|
|
+ <LinearLayout
|
|
+ android:layout_width="match_parent"
|
|
+ android:layout_height="wrap_content"
|
|
+ android:orientation="vertical">
|
|
<TextView
|
|
android:id="@+id/name"
|
|
android:layout_width="wrap_content"
|
|
android:layout_height="wrap_content"
|
|
android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
|
|
+ <TextView
|
|
+ android:id="@+id/url"
|
|
+ android:layout_width="wrap_content"
|
|
+ android:layout_height="wrap_content"
|
|
+ android:textAppearance="@style/TextAppearance.TextSmall.Secondary" />
|
|
+ </LinearLayout>
|
|
</LinearLayout>
|
|
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
|
|
@@ -94,6 +94,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
|
|
@@ -103,7 +103,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/browser/BUILD.gn b/components/adblock/content/browser/BUILD.gn
|
|
--- a/components/adblock/content/browser/BUILD.gn
|
|
+++ b/components/adblock/content/browser/BUILD.gn
|
|
@@ -14,15 +14,8 @@
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with eyeo Chromium SDK. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
-import("//components/adblock/features.gni")
|
|
-
|
|
config("adblock_content_common_config") {
|
|
defines = []
|
|
-
|
|
- if (eyeo_intercept_debug_url) {
|
|
- print("WARNING! Enabled intercepting eyeo debug url \"adblock.test.data\"")
|
|
- defines += [ "EYEO_INTERCEPT_DEBUG_URL=1" ]
|
|
- }
|
|
}
|
|
|
|
source_set("browser_impl") {
|
|
@@ -51,13 +44,6 @@ source_set("browser_impl") {
|
|
"session_stats_impl.h",
|
|
]
|
|
|
|
- if (eyeo_intercept_debug_url) {
|
|
- sources += [
|
|
- "adblock_url_loader_factory_for_test.cc",
|
|
- "adblock_url_loader_factory_for_test.h",
|
|
- ]
|
|
- }
|
|
-
|
|
deps = [
|
|
"//base",
|
|
"//components/resources:components_resources_grit",
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
-import("//components/adblock/features.gni")
|
|
import("//third_party/flatbuffers/flatbuffer.gni")
|
|
|
|
flatbuffer("schema") {
|
|
@@ -61,56 +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 {
|
|
- # 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 {
|
|
- 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 {
|
|
- 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\"" ]
|
|
- }
|
|
-
|
|
- if (eyeo_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",
|
|
@@ -134,8 +91,6 @@ source_set("core") {
|
|
"//components/prefs",
|
|
"//components/version_info",
|
|
]
|
|
-
|
|
- all_dependent_configs = [ ":adblock_core_config" ]
|
|
}
|
|
|
|
source_set("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,241 +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 <http://www.gnu.org/licenses/>.
|
|
- */
|
|
-
|
|
-#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 {
|
|
-int g_http_port_for_testing = 0;
|
|
-std::optional<base::TimeDelta> g_time_delta_for_testing;
|
|
-
|
|
-GURL GetUrl() {
|
|
- GURL url(EYEO_TELEMETRY_SERVER_URL);
|
|
- if (!g_http_port_for_testing) {
|
|
- return url;
|
|
- }
|
|
- DCHECK_EQ(url::kHttpsScheme, url.scheme());
|
|
- GURL::Replacements replacements;
|
|
- replacements.SetSchemeStr(url::kHttpScheme);
|
|
- const std::string port_str = base::NumberToString(g_http_port_for_testing);
|
|
- replacements.SetPortStr(port_str);
|
|
- return url.ReplaceComponents(replacements);
|
|
-}
|
|
-
|
|
-base::TimeDelta GetNormalPingInterval() {
|
|
- static base::TimeDelta kNormalPingInterval =
|
|
- g_time_delta_for_testing ? g_time_delta_for_testing.value()
|
|
- : base::Hours(8);
|
|
- return kNormalPingInterval;
|
|
-}
|
|
-
|
|
-base::TimeDelta GetRetryPingInterval() {
|
|
- static base::TimeDelta kRetryPingInterval =
|
|
- g_time_delta_for_testing ? g_time_delta_for_testing.value()
|
|
- : base::Hours(1);
|
|
- return kRetryPingInterval;
|
|
-}
|
|
-
|
|
-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,
|
|
- AdblockController* adblock_controller,
|
|
- const GURL& base_url,
|
|
- const std::string& auth_token)
|
|
- : app_info_(std::move(app_info)),
|
|
- pref_service_(pref_service),
|
|
- adblock_controller_(adblock_controller),
|
|
- 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 GetUrl();
|
|
-}
|
|
-
|
|
-// 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_;
|
|
-}
|
|
-
|
|
-void ActivepingTelemetryTopicProvider::GetPayload(PayloadCallback callback) {
|
|
- base::Value payload(base::Value::Type::DICT);
|
|
- 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",
|
|
- adblock_controller_->IsAcceptableAdsEnabled());
|
|
- 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::DICT);
|
|
- 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;
|
|
- std::move(callback).Run(std::move(serialized));
|
|
-}
|
|
-
|
|
-base::Time ActivepingTelemetryTopicProvider::GetTimeOfNextRequest() 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 ASAP.
|
|
- if (next_ping_time.is_null())
|
|
- return base::Time::Now();
|
|
-
|
|
- return next_ping_time;
|
|
-}
|
|
-
|
|
-void ActivepingTelemetryTopicProvider::ParseResponse(
|
|
- std::unique_ptr<std::string> response_content) {
|
|
- if (!response_content) {
|
|
- VLOG(1) << "[eyeo] Telemetry ping failed, no response from server";
|
|
- ScheduleNextPing(GetRetryPingInterval());
|
|
- 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(GetRetryPingInterval());
|
|
- return;
|
|
- }
|
|
-
|
|
- auto* error_message = parsed->FindStringKey("error");
|
|
- if (error_message) {
|
|
- VLOG(1) << "[eyeo] Telemetry ping failed, error message: "
|
|
- << *error_message;
|
|
- ScheduleNextPing(GetRetryPingInterval());
|
|
- 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(GetRetryPingInterval());
|
|
- return;
|
|
- }
|
|
-
|
|
- VLOG(1) << "[eyeo] Telemetry ping succeeded";
|
|
- ScheduleNextPing(GetNormalPingInterval());
|
|
- 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());
|
|
-}
|
|
-
|
|
-// static
|
|
-void ActivepingTelemetryTopicProvider::SetHttpPortForTesting(
|
|
- int http_port_for_testing) {
|
|
- g_http_port_for_testing = http_port_for_testing;
|
|
-}
|
|
-
|
|
-// static
|
|
-void ActivepingTelemetryTopicProvider::SetIntervalsForTesting(
|
|
- base::TimeDelta time_delta) {
|
|
- g_time_delta_for_testing = time_delta;
|
|
-}
|
|
-
|
|
-} // 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,83 +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 <http://www.gnu.org/licenses/>.
|
|
- */
|
|
-
|
|
-#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_controller.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,
|
|
- AdblockController* adblock_controller,
|
|
- 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;
|
|
- void GetPayload(PayloadCallback callback) final;
|
|
-
|
|
- // Normally 8 hours since last ping, 1 hour in case of retries.
|
|
- base::Time GetTimeOfNextRequest() const final;
|
|
-
|
|
- // Attempts to parse "token" (an opaque server description of last ping time)
|
|
- // from |response_content|.
|
|
- void ParseResponse(std::unique_ptr<std::string> response_content) final;
|
|
-
|
|
- // Sets the port used by the embedded http server required for browser tests.
|
|
- // Must be called before the first call to DefaultBaseUrl().
|
|
- static void SetHttpPortForTesting(int http_port_for_testing);
|
|
-
|
|
- // Sets the internal timing for sending pings required for browser tests.
|
|
- // Must be called before AdblockTelemetryService::Start().
|
|
- static void SetIntervalsForTesting(base::TimeDelta time_delta);
|
|
-
|
|
- private:
|
|
- void ScheduleNextPing(base::TimeDelta delay);
|
|
- void UpdatePrefs(const std::string& ping_response_time);
|
|
-
|
|
- const utils::AppInfo app_info_;
|
|
- PrefService* pref_service_;
|
|
- AdblockController* adblock_controller_;
|
|
- 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
|
|
@@ -129,6 +129,7 @@ bool AdblockControllerImpl::IsAdblockEnabled() const {
|
|
}
|
|
|
|
void AdblockControllerImpl::SetAcceptableAdsEnabled(bool enabled) {
|
|
+ enabled = false;
|
|
if (enabled) {
|
|
InstallSubscription(AcceptableAdsUrl());
|
|
} else {
|
|
@@ -143,6 +144,7 @@ bool AdblockControllerImpl::IsAcceptableAdsEnabled() const {
|
|
}
|
|
|
|
void AdblockControllerImpl::InstallSubscription(const GURL& url) {
|
|
+ if (url == AcceptableAdsUrl()) return;
|
|
adblock_filtering_configuration_->AddFilterList(url);
|
|
}
|
|
|
|
@@ -242,9 +244,7 @@ void AdblockControllerImpl::RunFirstRunLogic(PrefService* pref_service) {
|
|
// On first run, install additional subscriptions.
|
|
for (const auto& cur : known_subscriptions_) {
|
|
if (cur.first_run == SubscriptionFirstRunBehavior::Subscribe) {
|
|
- if (cur.url == AcceptableAdsUrl() &&
|
|
- base::CommandLine::ForCurrentProcess()->HasSwitch(
|
|
- switches::kDisableAcceptableAds)) {
|
|
+ if (cur.url == AcceptableAdsUrl()) {
|
|
// Do not install Acceptable Ads on first run because a command line
|
|
// switch forbids it. Mostly used for testing.
|
|
continue;
|
|
@@ -301,6 +301,7 @@ void AdblockControllerImpl::MigrateLegacyPrefs(PrefService* pref_service) {
|
|
}
|
|
|
|
void AdblockControllerImpl::InstallLanguageBasedRecommendedSubscriptions() {
|
|
+ if ((true)) return;
|
|
bool language_specific_subscription_installed = false;
|
|
for (const auto& subscription : known_subscriptions_) {
|
|
if (subscription.first_run ==
|
|
diff --git a/components/adblock/core/adblock_switches.cc b/components/adblock/core/adblock_switches.cc
|
|
--- a/components/adblock/core/adblock_switches.cc
|
|
+++ b/components/adblock/core/adblock_switches.cc
|
|
@@ -19,7 +19,6 @@
|
|
|
|
namespace adblock::switches {
|
|
|
|
-const char kDisableAcceptableAds[] = "disable-aa";
|
|
const char kDisableAdblock[] = "disable-adblock";
|
|
const char kDisableWebUiCompatibility[] = "disable-webui-compatibility";
|
|
|
|
diff --git a/components/adblock/core/adblock_switches.h b/components/adblock/core/adblock_switches.h
|
|
--- a/components/adblock/core/adblock_switches.h
|
|
+++ b/components/adblock/core/adblock_switches.h
|
|
@@ -20,7 +20,6 @@
|
|
|
|
namespace adblock::switches {
|
|
|
|
-extern const char kDisableAcceptableAds[];
|
|
extern const char kDisableAdblock[];
|
|
// TODO(mpawlowski) remove in 111, when this becomes standard:
|
|
extern const char kDisableWebUiCompatibility[];
|
|
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,244 +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 <http://www.gnu.org/licenses/>.
|
|
- */
|
|
-
|
|
-#include "components/adblock/core/adblock_telemetry_service.h"
|
|
-
|
|
-#include <string>
|
|
-
|
|
-#include "base/functional/bind.h"
|
|
-#include "base/memory/weak_ptr.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 'Ad blocking' 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<TopicProvider> topic_provider,
|
|
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
|
|
- : topic_provider_(std::move(topic_provider)),
|
|
- url_loader_factory_(url_loader_factory) {}
|
|
-
|
|
- bool IsRequestDue() {
|
|
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
- const auto due_time = topic_provider_->GetTimeOfNextRequest();
|
|
- if (due_time > base::Time::Now()) {
|
|
- VLOG(1) << "[eyeo] Telemetry request for "
|
|
- << topic_provider_->GetEndpointURL()
|
|
- << " not due yet, should run at " << due_time;
|
|
- return false;
|
|
- }
|
|
- if (IsRequestInFlight()) {
|
|
- VLOG(1) << "[eyeo] Telemetry request for "
|
|
- << topic_provider_->GetEndpointURL() << " already in-flight";
|
|
- return false;
|
|
- }
|
|
- VLOG(1) << "[eyeo] Telemetry request for "
|
|
- << topic_provider_->GetEndpointURL() << " is due";
|
|
- return true;
|
|
- }
|
|
-
|
|
- void StartRequest() {
|
|
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
- VLOG(1) << "[eyeo] Telemetry request for "
|
|
- << topic_provider_->GetEndpointURL() << " starting now";
|
|
- topic_provider_->GetPayload(base::BindOnce(&Conversation::MakeRequest,
|
|
- weak_ptr_factory_.GetWeakPtr()));
|
|
- }
|
|
-
|
|
- void Stop() {
|
|
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
- url_loader_.reset();
|
|
- }
|
|
-
|
|
- private:
|
|
- bool IsRequestInFlight() {
|
|
- return url_loader_ != nullptr || weak_ptr_factory_.HasWeakPtrs();
|
|
- }
|
|
-
|
|
- void MakeRequest(std::string payload) {
|
|
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
- auto request = std::make_unique<network::ResourceRequest>();
|
|
- 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);
|
|
-
|
|
- 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<std::string> server_response) {
|
|
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
- topic_provider_->ParseResponse(std::move(server_response));
|
|
- url_loader_.reset();
|
|
- }
|
|
-
|
|
- SEQUENCE_CHECKER(sequence_checker_);
|
|
- std::unique_ptr<TopicProvider> topic_provider_;
|
|
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
|
|
- std::unique_ptr<network::SimpleURLLoader> url_loader_;
|
|
- base::WeakPtrFactory<Conversation> weak_ptr_factory_{this};
|
|
-};
|
|
-
|
|
-AdblockTelemetryService::AdblockTelemetryService(
|
|
- FilteringConfiguration* filtering_configuration,
|
|
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
|
|
- base::TimeDelta initial_delay,
|
|
- base::TimeDelta check_interval)
|
|
- : adblock_filtering_configuration_(filtering_configuration),
|
|
- url_loader_factory_(url_loader_factory),
|
|
- initial_delay_(initial_delay),
|
|
- check_interval_(check_interval) {
|
|
- DCHECK(adblock_filtering_configuration_);
|
|
- adblock_filtering_configuration_->AddObserver(this);
|
|
-}
|
|
-
|
|
-AdblockTelemetryService::~AdblockTelemetryService() {
|
|
- DCHECK(adblock_filtering_configuration_);
|
|
- adblock_filtering_configuration_->RemoveObserver(this);
|
|
-}
|
|
-
|
|
-void AdblockTelemetryService::AddTopicProvider(
|
|
- std::unique_ptr<TopicProvider> topic_provider) {
|
|
- ongoing_conversations_.push_back(std::make_unique<Conversation>(
|
|
- std::move(topic_provider), url_loader_factory_));
|
|
-}
|
|
-
|
|
-void AdblockTelemetryService::Start() {
|
|
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
- OnEnabledStateChangedInternal();
|
|
-}
|
|
-
|
|
-void AdblockTelemetryService::OnEnabledStateChanged(FilteringConfiguration*) {
|
|
- OnEnabledStateChangedInternal();
|
|
-}
|
|
-
|
|
-void AdblockTelemetryService::OnEnabledStateChangedInternal() {
|
|
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
- if (adblock_filtering_configuration_->IsEnabled() && !timer_.IsRunning()) {
|
|
- VLOG(1) << "[eyeo] Starting periodic Telemetry requests";
|
|
- timer_.Start(FROM_HERE, initial_delay_,
|
|
- base::BindRepeating(&AdblockTelemetryService::RunPeriodicCheck,
|
|
- base::Unretained(this)));
|
|
- } else if (!adblock_filtering_configuration_->IsEnabled() &&
|
|
- timer_.IsRunning()) {
|
|
- VLOG(1) << "[eyeo] Stopping periodic Telemetry requests";
|
|
- Shutdown();
|
|
- }
|
|
-}
|
|
-
|
|
-void AdblockTelemetryService::RunPeriodicCheck() {
|
|
- for (auto& conversation : ongoing_conversations_) {
|
|
- if (conversation->IsRequestDue()) {
|
|
- conversation->StartRequest();
|
|
- }
|
|
- }
|
|
- timer_.Start(FROM_HERE, check_interval_,
|
|
- base::BindRepeating(&AdblockTelemetryService::RunPeriodicCheck,
|
|
- base::Unretained(this)));
|
|
-}
|
|
-
|
|
-void AdblockTelemetryService::Shutdown() {
|
|
- timer_.Stop();
|
|
- 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,106 +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 <http://www.gnu.org/licenses/>.
|
|
- */
|
|
-
|
|
-#ifndef COMPONENTS_ADBLOCK_CORE_ADBLOCK_TELEMETRY_SERVICE_H_
|
|
-#define COMPONENTS_ADBLOCK_CORE_ADBLOCK_TELEMETRY_SERVICE_H_
|
|
-
|
|
-#include <memory>
|
|
-#include <string>
|
|
-#include <vector>
|
|
-
|
|
-#include "base/sequence_checker.h"
|
|
-#include "base/time/time.h"
|
|
-#include "base/timer/timer.h"
|
|
-#include "components/adblock/core/configuration/filtering_configuration.h"
|
|
-#include "components/adblock/core/subscription/subscription_service.h"
|
|
-#include "components/keyed_service/core/keyed_service.h"
|
|
-#include "services/network/public/cpp/shared_url_loader_factory.h"
|
|
-#include "url/gurl.h"
|
|
-
|
|
-namespace network {
|
|
-class SimpleURLLoader;
|
|
-} // namespace network
|
|
-
|
|
-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 FilteringConfiguration::Observer {
|
|
- 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:
|
|
- using PayloadCallback = base::OnceCallback<void(std::string payload)>;
|
|
- 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. Async to allow querying asynchronous data sources.
|
|
- virtual void GetPayload(PayloadCallback callback) = 0;
|
|
- // Returns the desired time when AdblockTelemetryService should make the
|
|
- // next network request.
|
|
- virtual base::Time GetTimeOfNextRequest() 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<std::string> response_content) = 0;
|
|
- };
|
|
- AdblockTelemetryService(
|
|
- FilteringConfiguration* filtering_configuration,
|
|
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
|
|
- base::TimeDelta initial_delay,
|
|
- base::TimeDelta check_interval);
|
|
- ~AdblockTelemetryService() override;
|
|
-
|
|
- // Add all required topic providers before calling Start().
|
|
- void AddTopicProvider(std::unique_ptr<TopicProvider> topic_provider);
|
|
-
|
|
- // Starts periodic Telemetry requests, provided ad-blocking is enabled.
|
|
- // If ad blocking is disabled, the schedule will instead start when
|
|
- // ad blocking becomes enabled.
|
|
- void Start();
|
|
-
|
|
- // KeyedService:
|
|
- void Shutdown() override;
|
|
-
|
|
- // FilteringConfiguration::Observer
|
|
- void OnEnabledStateChanged(FilteringConfiguration* config) override;
|
|
-
|
|
- private:
|
|
- void OnEnabledStateChangedInternal();
|
|
- void RunPeriodicCheck();
|
|
-
|
|
- SEQUENCE_CHECKER(sequence_checker_);
|
|
- FilteringConfiguration* adblock_filtering_configuration_;
|
|
- scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
|
|
- base::TimeDelta initial_delay_;
|
|
- base::TimeDelta check_interval_;
|
|
-
|
|
- class Conversation;
|
|
- std::vector<std::unique_ptr<Conversation>> ongoing_conversations_;
|
|
- base::OneShotTimer timer_;
|
|
-};
|
|
-
|
|
-} // 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
|
|
@@ -65,56 +65,18 @@ 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(kEnableAdblockLegacy, true);
|
|
- registry->RegisterBooleanPref(kEnableAcceptableAdsLegacy, true);
|
|
- registry->RegisterBooleanPref(kAdblockMoreOptionsEnabled, false);
|
|
+ registry->RegisterBooleanPref(kEnableAcceptableAdsLegacy, false);
|
|
+ registry->RegisterBooleanPref(kAdblockMoreOptionsEnabled, true);
|
|
registry->RegisterListPref(kAdblockAllowedDomainsLegacy, {});
|
|
registry->RegisterListPref(kAdblockCustomFiltersLegacy, {});
|
|
registry->RegisterListPref(kAdblockSubscriptionsLegacy, {});
|
|
registry->RegisterListPref(kAdblockCustomSubscriptionsLegacy, {});
|
|
- registry->RegisterBooleanPref(kInstallFirstStartSubscriptions, true);
|
|
+ registry->RegisterBooleanPref(kInstallFirstStartSubscriptions, false);
|
|
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<net::HttpResponseHeaders>& 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/parser/metadata.cc b/components/adblock/core/converter/parser/metadata.cc
|
|
--- a/components/adblock/core/converter/parser/metadata.cc
|
|
+++ b/components/adblock/core/converter/parser/metadata.cc
|
|
@@ -40,7 +40,7 @@ absl::optional<Metadata> Metadata::FromStream(std::istream& filter_stream) {
|
|
std::string line;
|
|
std::getline(filter_stream, line);
|
|
if (!IsValidAdblockHeader(line)) {
|
|
- VLOG(1) << "[eyeo] Invalid filter list. Should start with [Adblock Plus "
|
|
+ LOG(ERROR) << "[eyeo] Invalid filter list. Should start with [Adblock Plus "
|
|
"<x>.<y>].";
|
|
return {};
|
|
}
|
|
@@ -62,7 +62,7 @@ absl::optional<Metadata> Metadata::FromStream(std::istream& filter_stream) {
|
|
if (url.is_valid()) {
|
|
redirect_url = url;
|
|
} else {
|
|
- VLOG(1) << "[eyeo] Invalid redirect URL: " << value
|
|
+ LOG(ERROR) << "[eyeo] Invalid redirect URL: " << value
|
|
<< ". Will not redirect.";
|
|
}
|
|
} else if (key == "title") {
|
|
@@ -131,7 +131,7 @@ base::TimeDelta Metadata::ParseExpirationTime(
|
|
|
|
if (!re2::RE2::FullMatch(expiration_value, expiration_time_re,
|
|
&expiration_time, &expiration_unit)) {
|
|
- VLOG(1) << "[eyeo] Invalid expiration time format: " << expiration_value
|
|
+ LOG(ERROR) << "[eyeo] Invalid expiration time format: " << expiration_value
|
|
<< ". Will use default value of "
|
|
<< kDefaultExpirationInterval.InDays() << " days.";
|
|
return kDefaultExpirationInterval;
|
|
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<net::HttpResponseHeaders>& 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<GURL>& 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/filtering_configuration_maintainer_impl.cc b/components/adblock/core/subscription/filtering_configuration_maintainer_impl.cc
|
|
--- a/components/adblock/core/subscription/filtering_configuration_maintainer_impl.cc
|
|
+++ b/components/adblock/core/subscription/filtering_configuration_maintainer_impl.cc
|
|
@@ -282,7 +282,6 @@ void FilteringConfigurationMaintainerImpl::RunUpdateCheck() {
|
|
AcceptableAdsUrl();
|
|
}) &&
|
|
persistent_metadata_->IsExpired(AcceptableAdsUrl())) {
|
|
- PingAcceptableAds();
|
|
}
|
|
}
|
|
|
|
@@ -374,15 +373,6 @@ void FilteringConfigurationMaintainerImpl::SubscriptionAddedToStorage(
|
|
subscription_updated_callback_.Run(subscription->GetSourceUrl());
|
|
}
|
|
|
|
-void FilteringConfigurationMaintainerImpl::PingAcceptableAds() {
|
|
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
- DCHECK(IsInitialized());
|
|
- downloader_->DoHeadRequest(
|
|
- AcceptableAdsUrl(),
|
|
- base::BindOnce(&FilteringConfigurationMaintainerImpl::OnHeadRequestDone,
|
|
- weak_ptr_factory_.GetWeakPtr()));
|
|
-}
|
|
-
|
|
void FilteringConfigurationMaintainerImpl::OnHeadRequestDone(
|
|
const std::string version) {
|
|
if (version.empty()) {
|
|
diff --git a/components/adblock/core/subscription/filtering_configuration_maintainer_impl.h b/components/adblock/core/subscription/filtering_configuration_maintainer_impl.h
|
|
--- a/components/adblock/core/subscription/filtering_configuration_maintainer_impl.h
|
|
+++ b/components/adblock/core/subscription/filtering_configuration_maintainer_impl.h
|
|
@@ -83,7 +83,6 @@ class FilteringConfigurationMaintainerImpl
|
|
void SubscriptionAddedToStorage(
|
|
scoped_refptr<OngoingInstallation> ongoing_installation,
|
|
scoped_refptr<InstalledSubscription> subscription);
|
|
- void PingAcceptableAds();
|
|
void OnHeadRequestDone(const std::string version);
|
|
void UninstallSubscription(const GURL& subscription_url);
|
|
bool UninstallSubscriptionInternal(const GURL& subscription_url);
|
|
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
|
|
@@ -22,6 +22,7 @@
|
|
#include "base/strings/string_piece_forward.h"
|
|
#include "base/task/thread_pool.h"
|
|
#include "base/trace_event/trace_event.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"
|
|
@@ -44,11 +45,23 @@ const net::NetworkTrafficAnnotationTag kTrafficAnnotation =
|
|
"Application name (ex. Chromium) "
|
|
"Application version (93.0.4572.0) "
|
|
destination: WEBSITE
|
|
+ internal {
|
|
+ contacts {
|
|
+ email: "uazo@users.noreply.github.com"
|
|
+ }
|
|
+ contacts {
|
|
+ email: "uazo@users.noreply.github.com"
|
|
+ }
|
|
+ }
|
|
+ user_data {
|
|
+ type: NONE
|
|
+ }
|
|
+ last_reviewed: "2023-01-01"
|
|
}
|
|
policy {
|
|
cookies_allowed: NO
|
|
setting:
|
|
- "You enable or disable this feature via 'Ad blocking' setting."
|
|
+ "You enable or disable this feature via 'Adblock Enable' pref."
|
|
policy_exception_justification: "Not implemented."
|
|
})");
|
|
|
|
@@ -64,7 +77,7 @@ OngoingSubscriptionRequestImpl::OngoingSubscriptionRequestImpl(
|
|
|
|
OngoingSubscriptionRequestImpl::~OngoingSubscriptionRequestImpl() {
|
|
if (!url_.is_empty())
|
|
- VLOG(1) << "[eyeo] Cancelling download of " << url_;
|
|
+ LOG(INFO) << "[eyeo] Cancelling download of " << url_;
|
|
}
|
|
|
|
void OngoingSubscriptionRequestImpl::Start(GURL url,
|
|
@@ -86,7 +99,7 @@ void OngoingSubscriptionRequestImpl::Retry() {
|
|
return;
|
|
}
|
|
backoff_entry_->InformOfRequest(false);
|
|
- VLOG(1) << "[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(),
|
|
@@ -100,7 +113,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";
|
|
- VLOG(1) << "[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();
|
|
@@ -120,10 +133,14 @@ void OngoingSubscriptionRequestImpl::StartInternal() {
|
|
// indefinitely.
|
|
return;
|
|
}
|
|
- VLOG(1) << "[eyeo] Downloading " << url_;
|
|
+ LOG(INFO) << "[eyeo] Downloading " << url_;
|
|
auto request = std::make_unique<network::ResourceRequest>();
|
|
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);
|
|
|
|
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
|
|
@@ -63,10 +63,10 @@ class PreloadedSubscriptionProviderImpl::SingleSubscriptionProvider {
|
|
utils::MakeFlatbufferDataFromResourceBundle(
|
|
info_.flatbuffer_resource_id),
|
|
Subscription::InstallationState::Preloaded, base::Time());
|
|
- VLOG(1) << "[eyeo] Preloaded subscription now in use: "
|
|
+ LOG(INFO) << "[eyeo] Preloaded subscription now in use: "
|
|
<< subscription_->GetSourceUrl();
|
|
} else if (!needs_subscription && subscription_) {
|
|
- VLOG(1) << "[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
|
|
@@ -230,7 +230,7 @@ const std::vector<KnownSubscriptionInfo>& config::GetKnownSubscriptions() {
|
|
"ABP filters",
|
|
{},
|
|
SubscriptionUiVisibility::Visible,
|
|
- SubscriptionFirstRunBehavior::Subscribe,
|
|
+ SubscriptionFirstRunBehavior::Ignore,
|
|
SubscriptionPrivilegedFilterStatus::Allowed},
|
|
{GURL(GetHost() + "i_dont_care_about_cookies.txt"),
|
|
"I don't care about cookies",
|
|
@@ -294,6 +294,8 @@ const std::vector<KnownSubscriptionInfo>& 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 ==
|
|
@@ -307,9 +309,7 @@ bool config::AllowPrivilegedFilters(const GURL& url) {
|
|
const std::vector<PreloadedSubscriptionInfo>&
|
|
config::GetPreloadedSubscriptionConfiguration() {
|
|
static const std::vector<PreloadedSubscriptionInfo> 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<RetryPolicy>(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<OngoingRequestPtr>(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<DownloadCompletedCallback>(download_it->second))
|
|
.Run(nullptr);
|
|
@@ -229,14 +226,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;
|
|
}
|
|
|
|
if (absl::holds_alternative<std::unique_ptr<FlatbufferData>>(
|
|
converter_result)) {
|
|
- VLOG(1) << "[eyeo] Finished converting " << subscription_url
|
|
+ LOG(WARNING) << "[eyeo] Finished converting " << subscription_url
|
|
<< " successfully";
|
|
std::move(std::get<DownloadCompletedCallback>(download_it->second))
|
|
.Run(std::move(
|
|
@@ -279,7 +276,7 @@ void SubscriptionDownloaderImpl::AbortWithWarning(
|
|
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<DownloadCompletedCallback>(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
|
|
@@ -116,6 +116,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",
|
|
@@ -123,6 +125,8 @@ SubscriptionPersistentStorageImpl::ReadSubscriptionsFromDirectory(
|
|
TRACE_EVENT_BEGIN0("eyeo", "VerifySubscriptionBuffer");
|
|
if (!is_signature_valid.Run(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_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
|
|
@@ -113,7 +113,7 @@ void SubscriptionServiceImpl::OnEnabledStateChanged(
|
|
});
|
|
DCHECK(it != maintainers_.end()) << "Received OnEnabledStateChanged from "
|
|
"unregistered FilteringConfiguration";
|
|
- VLOG(1) << "[eyeo] FilteringConfiguration " << config->GetName()
|
|
+ LOG(INFO) << "[eyeo] FilteringConfiguration " << config->GetName()
|
|
<< (config->IsEnabled() ? " enabled" : " disabled");
|
|
if (config->IsEnabled()) {
|
|
// Enable the configuration by creating a new
|
|
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
|
|
@@ -38,7 +38,7 @@ void SubscriptionUpdaterImpl::StartSchedule(
|
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
DCHECK(!timer_.IsRunning());
|
|
run_update_check_ = std::move(run_update_check);
|
|
- VLOG(1) << "[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,
|
|
@@ -47,14 +47,14 @@ void SubscriptionUpdaterImpl::StartSchedule(
|
|
|
|
void SubscriptionUpdaterImpl::StopSchedule() {
|
|
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
|
- VLOG(1) << "[eyeo] Stopping update schedule";
|
|
+ LOG(INFO) << "[eyeo] Stopping update schedule";
|
|
timer_.Stop();
|
|
}
|
|
|
|
void SubscriptionUpdaterImpl::RunUpdateCheck() {
|
|
- VLOG(1) << "[eyeo] Running subscription update check";
|
|
+ LOG(INFO) << "[eyeo] Running subscription update check";
|
|
run_update_check_.Run();
|
|
- VLOG(1)
|
|
+ LOG(INFO)
|
|
<< "[eyeo] Subscription update check completed, next one scheduled for "
|
|
<< base::Time::Now() + check_interval_;
|
|
timer_.Start(FROM_HERE, check_interval_,
|
|
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,11 +65,11 @@ bool IsSignatureValidInternal(
|
|
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/adblock/features.gni b/components/adblock/features.gni
|
|
deleted file mode 100644
|
|
--- a/components/adblock/features.gni
|
|
+++ /dev/null
|
|
@@ -1,44 +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 <http://www.gnu.org/licenses/>.
|
|
-
|
|
-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 = ""
|
|
-
|
|
- # If true then requests to "adblock.test.data" domain will be intercepted
|
|
- # in order to allow installing/removing/listing filter lists via navigating to
|
|
- # special URLs. This is used for internal automated testing (see DPD-1407).
|
|
- eyeo_intercept_debug_url = false
|
|
-}
|
|
diff --git a/components/resources/BUILD.gn b/components/resources/BUILD.gn
|
|
--- a/components/resources/BUILD.gn
|
|
+++ b/components/resources/BUILD.gn
|
|
@@ -75,7 +75,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 @@
|
|
<include name="IDR_ADBLOCK_ELEMHIDE_FOR_SELECTOR_JS" file="adblocking/elemhide_for_selector.jst" type="BINDATA" />
|
|
<include name="IDR_ADBLOCK_ELEMHIDE_EMU_JS" file="adblocking/elemhideemu.jst" type="BINDATA" />
|
|
<include name="IDR_ADBLOCK_SNIPPETS_JS" file="${root_gen_dir}/components/resources/adblocking/snippets.jst" use_base_dir="false" type="BINDATA" compress="gzip" />
|
|
- <include name="IDR_ADBLOCK_FLATBUFFER_EASYLIST" file="${root_gen_dir}/components/resources/adblocking/easylist.fb" use_base_dir="false" type="BINDATA" compress="gzip" />
|
|
- <include name="IDR_ADBLOCK_FLATBUFFER_EXCEPTIONRULES" file="${root_gen_dir}/components/resources/adblocking/exceptionrules.fb" use_base_dir="false" type="BINDATA" compress="gzip" />
|
|
- <include name="IDR_ADBLOCK_FLATBUFFER_ANTICV" file="${root_gen_dir}/components/resources/adblocking/anticv.fb" use_base_dir="false" type="BINDATA" compress="gzip" />
|
|
</grit-part>
|
|
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 ]
|
|
@@ -31,34 +31,6 @@ 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.gz"
|
|
- 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.gz"
|
|
- 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.gz"
|
|
- url = "https://easylist-downloads.adblockplus.org/abp-filters-anti-cv.txt"
|
|
- output = "${target_gen_dir}/anticv.fb"
|
|
-}
|
|
-
|
|
-group("make_all_preloaded_subscriptions") {
|
|
- deps = [
|
|
- ":make_anticv",
|
|
- ":make_easylist",
|
|
- ":make_exceptionrules",
|
|
- ]
|
|
-}
|
|
-
|
|
copy("copy_snippets_lib") {
|
|
if (is_debug) {
|
|
sources = [ "//components/resources/adblocking/snippets/dist/isolated-first.source.jst" ]
|
|
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 <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+ ((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;n<o;n++)e(t.snapshotItem(n))}}return t=>je(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<r;)o[0][i]=i;for(i=0;++i<n;){const n=e[s];let l=0,a=0;for(o[i]=[i];++l<r;)o[i][l]=Ct(o[s][l]+1,o[i][a]+1,o[s][a]+(n!=t[a])),++a;++s}return o[n-1][r-1]};let{getComputedStyle:Nt,Map:Lt,WeakSet:At,parseFloat:Rt}=ke(window);const{ELEMENT_NODE:Vt,TEXT_NODE:It}=Node;let{MutationObserver:jt}=ke(window);let{getComputedStyle:Ht,MutationObserver:$t,WeakSet:_t}=ke(window);ke(window);const Bt={mark(){},end(){},toString:()=>"{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;i<o;i++){const o=ke(n).substr(i,c);if(Wt(u,ke([...o]).sort())-r<=0){const n=ke(e).closest(t);if(s("Found similar text: "+l,n),n){h(),Fe(n);break}}}}};let p=new Ot(d),h=wt("hide-if-contains-similar-text",(()=>p.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.length<t&&(n=ke("0").repeat(t-n.length)+n);return n}(t)),""))){let n=ke(e).closest(t);n&&(s(),Fe(n))}}))}},i=new Et(o),s=wt("hide-if-contains-image",(()=>i.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<n.length-1;e++){let t=n[e];if(!m(r,t))return;if(r=r[t],!(r instanceof it))return}let o=n[n.length-1];return m(r,o)?[r,o]:void 0}const at=je(/^\d+$/);function lt(e){switch(e){case"false":return!1;case"true":return!0;case"null":return null;case"noopFunc":return()=>{};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;r<o;r++)e(t.snapshotItem(r))}}return t=>Ot(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;l<o.length;l++){let c=o[l],u=i[l],f=()=>c.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 <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+ ((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 <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+ 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 <http://www.gnu.org/licenses/>.
|
|
+ */
|
|
+ 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
|
|
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc
|
|
--- a/third_party/blink/renderer/core/css/style_engine.cc
|
|
+++ b/third_party/blink/renderer/core/css/style_engine.cc
|
|
@@ -539,6 +539,14 @@ void StyleEngine::UpdateActiveStyleSheetsInShadow(
|
|
}
|
|
}
|
|
|
|
+bool StyleEngine::ActiveUserStyleSheetsContainsKey(const StyleSheetKey& injection_key) {
|
|
+ for (auto& sheet : injected_user_style_sheets_)
|
|
+ if (sheet.first == injection_key)
|
|
+ return true;
|
|
+
|
|
+ return false;
|
|
+}
|
|
+
|
|
void StyleEngine::UpdateActiveUserStyleSheets() {
|
|
DCHECK(user_style_dirty_);
|
|
|
|
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h
|
|
--- a/third_party/blink/renderer/core/css/style_engine.h
|
|
+++ b/third_party/blink/renderer/core/css/style_engine.h
|
|
@@ -239,6 +239,7 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
|
|
const ComputedStyle* embedder_style) const;
|
|
void ViewportStyleSettingChanged();
|
|
|
|
+ bool ActiveUserStyleSheetsContainsKey(const StyleSheetKey& injection_key);
|
|
void InjectSheet(const StyleSheetKey&,
|
|
StyleSheetContents*,
|
|
WebCssOrigin = WebCssOrigin::kAuthor);
|
|
diff --git a/third_party/blink/renderer/core/exported/web_document.cc b/third_party/blink/renderer/core/exported/web_document.cc
|
|
--- a/third_party/blink/renderer/core/exported/web_document.cc
|
|
+++ b/third_party/blink/renderer/core/exported/web_document.cc
|
|
@@ -270,6 +270,16 @@ WebStyleSheetKey WebDocument::InsertAbpElemhideStylesheet(
|
|
Document* document = Unwrap<Document>();
|
|
DCHECK(document);
|
|
|
|
+ const WebStyleSheetKey& injection_key =
|
|
+ key && !key->IsNull() ? *key : WebString::FromUTF8("abp");
|
|
+ DCHECK(!injection_key.IsEmpty());
|
|
+
|
|
+ // Check if the css in already present
|
|
+ if (document->GetStyleEngine().ActiveUserStyleSheetsContainsKey(injection_key)) {
|
|
+ LOG(WARNING) << "[eyeo] Skip add css as already in collection";
|
|
+ return injection_key;
|
|
+ }
|
|
+
|
|
auto* parsed_sheet = MakeGarbageCollected<StyleSheetContents>(
|
|
MakeGarbageCollected<CSSParserContext>(*document));
|
|
parsed_sheet->ParseString(source_code);
|
|
@@ -291,9 +301,6 @@ WebStyleSheetKey WebDocument::InsertAbpElemhideStylesheet(
|
|
{SchedulingPolicy::DisableBackForwardCache()});
|
|
}
|
|
|
|
- const WebStyleSheetKey& injection_key =
|
|
- key && !key->IsNull() ? *key : GenerateStyleSheetKey();
|
|
- DCHECK(!injection_key.IsEmpty());
|
|
document->GetStyleEngine().InjectSheet(injection_key, parsed_sheet, origin);
|
|
return injection_key;
|
|
}
|
|
--
|
|
2.25.1
|