From 2918b103799fb23e96e16df70eff49f87778b373 Mon Sep 17 00:00:00 2001 From: Pete Smith Date: Fri, 2 Aug 2024 14:05:21 +0200 Subject: [PATCH 01/32] Improve sorting logic and related test (#3064) Task/Issue URL: **Description**: Applies changes already in main to the release branch --- ...erProtectionMigrationsFeatureFlagger.swift | 47 +-------- .../DataBrokerProtection/UI/UIMapper.swift | 9 +- ...tectionMigrationsFeatureFlaggerTests.swift | 96 ++----------------- .../MapperToUITests.swift | 14 +-- 4 files changed, 27 insertions(+), 139 deletions(-) diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Storage/DataBrokerProtectionMigrationsFeatureFlagger.swift b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Storage/DataBrokerProtectionMigrationsFeatureFlagger.swift index 15d8841fcfb..e95b0072972 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Storage/DataBrokerProtectionMigrationsFeatureFlagger.swift +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/Storage/DataBrokerProtectionMigrationsFeatureFlagger.swift @@ -18,34 +18,6 @@ import Foundation -protocol DateRangeChecker { - func isWithinRange(date: Date) -> Bool -} - -private struct DefaultDateRangeChecker: DateRangeChecker { - - func isWithinRange(date: Date) -> Bool { - let calendar = Calendar.current - - var startDateComponents = DateComponents() - startDateComponents.year = 2024 - startDateComponents.month = 7 - startDateComponents.day = 25 - - var endDateComponents = DateComponents() - endDateComponents.year = 2024 - endDateComponents.month = 8 - endDateComponents.day = 2 - - guard let startDate = calendar.date(from: startDateComponents), - let endDate = calendar.date(from: endDateComponents) else { - return false - } - - return (startDate...endDate).contains(date) - } -} - /// Conforming types provide a `isUserIn` method to check if a user is part of the specified % feature rollout protocol DataBrokerProtectionMigrationsFeatureFlagger { func isUserIn(percent: Int) -> Bool @@ -58,12 +30,9 @@ final class DefaultDataBrokerProtectionMigrationsFeatureFlagger: DataBrokerProte } private var userDefaults: UserDefaults - private var dateRangeChecker: DateRangeChecker - init(userDefaults: UserDefaults = .dbp, - dateRangeChecker: DateRangeChecker = DefaultDateRangeChecker()) { + init(userDefaults: UserDefaults = .dbp) { self.userDefaults = userDefaults - self.dateRangeChecker = dateRangeChecker } /// Checks if a user is part of the specified % feature rollout @@ -71,20 +40,6 @@ final class DefaultDataBrokerProtectionMigrationsFeatureFlagger: DataBrokerProte /// - Returns: True or false func isUserIn(percent: Int) -> Bool { - /* - START - Note: The following is temporary code intended to enable the feature flag for all users - prior to public release. This is to enable internal testing. - - Asana to Remove this code: https://app.asana.com/0/1206488453854252/1207876679488680/f - */ - if dateRangeChecker.isWithinRange(date: Date()) { - return true - } - /* - END - */ - guard let storedNumber = storedRandomNumber else { let generatedNumber = Int.random(in: 1...100) diff --git a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/UI/UIMapper.swift b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/UI/UIMapper.swift index 68e7c8671dc..04001ca81ee 100644 --- a/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/UI/UIMapper.swift +++ b/LocalPackages/DataBrokerProtection/Sources/DataBrokerProtection/UI/UIMapper.swift @@ -373,7 +373,14 @@ private extension Array where Element == [BrokerProfileQueryData] { /// - Returns: An array of `[BrokerProfileQueryData]` values sorted by the first `lastRunDate` of each element func sortedByLastRunDate() -> Self { self.sorted { lhs, rhs in - lhs.first?.scanJobData.lastRunDate < rhs.first?.scanJobData.lastRunDate + let lhsDate = lhs.first?.scanJobData.lastRunDate + let rhsDate = rhs.first?.scanJobData.lastRunDate + + if lhsDate == rhsDate { + return lhs.first?.dataBroker.name ?? "" < rhs.first?.dataBroker.name ?? "" + } else { + return lhsDate < rhsDate + } } } } diff --git a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionMigrationsFeatureFlaggerTests.swift b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionMigrationsFeatureFlaggerTests.swift index 310b37a8de4..9dcc513e7f1 100644 --- a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionMigrationsFeatureFlaggerTests.swift +++ b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionMigrationsFeatureFlaggerTests.swift @@ -19,45 +19,6 @@ import XCTest @testable import DataBrokerProtection -private final class MockDateRangeChecker: DateRangeChecker { - - private let startDateComponents: DateComponents - private let endDateComponents: DateComponents - - init(startDateComponents: DateComponents, endDateComponents: DateComponents) { - self.startDateComponents = startDateComponents - self.endDateComponents = endDateComponents - } - - func isWithinRange(date: Date) -> Bool { - let calendar = Calendar.current - - guard let startDate = calendar.date(from: startDateComponents), - let endDate = calendar.date(from: endDateComponents) else { - return false - } - - return (startDate...endDate).contains(date) - } -} - -extension MockDateRangeChecker { - static var inthePast: MockDateRangeChecker { - - var startDateComponents = DateComponents() - startDateComponents.year = 2020 - startDateComponents.month = 7 - startDateComponents.day = 25 - - var endDateComponents = DateComponents() - endDateComponents.year = 2020 - endDateComponents.month = 8 - endDateComponents.day = 2 - - return MockDateRangeChecker(startDateComponents: startDateComponents, endDateComponents: endDateComponents) - } -} - final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { private var userDefaults: UserDefaults! @@ -77,8 +38,7 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { func testRandomNumberGeneration() { // Given - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults, - dateRangeChecker: MockDateRangeChecker.inthePast) + let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults) XCTAssertNil(userDefaults.object(forKey: key)) // When @@ -90,8 +50,7 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { func testRandomNumberGenerationAndReuse() { // Given - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults, - dateRangeChecker: MockDateRangeChecker.inthePast) + let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults) XCTAssertNil(userDefaults.object(forKey: key)) // When @@ -110,8 +69,7 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { func testInPercentLogicForInputValue0AndPercent0() { // Given userDefaults.set(0, forKey: key) - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults, - dateRangeChecker: MockDateRangeChecker.inthePast) + let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults) // When let result = sut.isUserIn(percent: 0) @@ -124,8 +82,7 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { func testInPercentLogicForInputValue0AndPercent1() { // Given userDefaults.set(0, forKey: key) - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults, - dateRangeChecker: MockDateRangeChecker.inthePast) + let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults) // When let result = sut.isUserIn(percent: 1) @@ -138,8 +95,7 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { func testInPercentLogicForInputValue10AndPercent10() { // Given userDefaults.set(10, forKey: key) - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults, - dateRangeChecker: MockDateRangeChecker.inthePast) + let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults) // When let result = sut.isUserIn(percent: 10) @@ -152,8 +108,7 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { func testInPercentLogicForInputValue15AndPercent10() { // Given userDefaults.set(15, forKey: key) - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults, - dateRangeChecker: MockDateRangeChecker.inthePast) + let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults) // When let result = sut.isUserIn(percent: 10) @@ -166,8 +121,7 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { func testInPercentLogicForInputValue99AndPercent100() { // Given userDefaults.set(99, forKey: key) - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults, - dateRangeChecker: MockDateRangeChecker.inthePast) + let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults) // When let result = sut.isUserIn(percent: 100) @@ -180,8 +134,7 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { func testInPercentLogicForInputValue100AndPercent99() { // Given userDefaults.set(100, forKey: key) - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults, - dateRangeChecker: MockDateRangeChecker.inthePast) + let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults) // When let result = sut.isUserIn(percent: 99) @@ -194,8 +147,7 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { func testInPercentLogicForInputValue100AndPercent100() { // Given userDefaults.set(100, forKey: key) - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults, - dateRangeChecker: MockDateRangeChecker.inthePast) + let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults) // When let result = sut.isUserIn(percent: 100) @@ -215,8 +167,7 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { repeat { userDefaults.set(nil, forKey: key) - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults, - dateRangeChecker: MockDateRangeChecker.inthePast) + let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults) let result = sut.isUserIn(percent: 10) results.append(result) } while results.count < 100 @@ -235,31 +186,4 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { let average = sum / Double(percentages.count) XCTAssert(average > 9.0 && average < 11.0) } - - func testDateWithinDefaultTemporaryWindowReturnsTrue() { - // Given - userDefaults.set(100, forKey: key) - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults) - - // When - let result = sut.isUserIn(percent: 99) - - // Then - XCTAssertEqual(userDefaults.object(forKey: key) as? Int, 100) - XCTAssertTrue(result) - } - - func testDateWithinPastWindowReturnsFalse() { - // Given - userDefaults.set(100, forKey: key) - let sut = DefaultDataBrokerProtectionMigrationsFeatureFlagger(userDefaults: userDefaults, - dateRangeChecker: MockDateRangeChecker.inthePast) - - // When - let result = sut.isUserIn(percent: 99) - - // Then - XCTAssertEqual(userDefaults.object(forKey: key) as? Int, 100) - XCTAssertFalse(result) - } } diff --git a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/MapperToUITests.swift b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/MapperToUITests.swift index 02a1efb8521..a47d13d87a0 100644 --- a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/MapperToUITests.swift +++ b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/MapperToUITests.swift @@ -362,26 +362,28 @@ final class MapperToUITests: XCTestCase { func testBrokersWithMixedScanProgress_areOrderedByLastRunDate_andHaveCorrectStatus() { // Given + let minusTwoHours = Date.minusTwoHours + let minusThreeHours = Date.minusThreeHours let brokerProfileQueryData: [BrokerProfileQueryData] = [ .mock(dataBrokerName: "Broker #1", lastRunDate: Date()), .mock(dataBrokerName: "Broker #1", lastRunDate: Date()), - .mock(dataBrokerName: "Broker #1", lastRunDate: .minusTwoHours), + .mock(dataBrokerName: "Broker #1", lastRunDate: minusTwoHours), .mock(dataBrokerName: "Broker #2"), .mock(dataBrokerName: "Broker #2", lastRunDate: .minusOneHour), - .mock(dataBrokerName: "Broker #2", lastRunDate: .minusThreeHours), - .mock(dataBrokerName: "Broker #3", lastRunDate: .minusTwoHours), + .mock(dataBrokerName: "Broker #2", lastRunDate: minusThreeHours), + .mock(dataBrokerName: "Broker #3", lastRunDate: minusTwoHours), .mock(dataBrokerName: "Broker #3"), .mock(dataBrokerName: "Broker #3", lastRunDate: Date()), .mock(dataBrokerName: "Broker #4"), .mock(dataBrokerName: "Broker #5"), - .mock(dataBrokerName: "Broker #7", lastRunDate: .minusThreeHours), - .mock(dataBrokerName: "Broker #6", lastRunDate: .minusThreeHours) + .mock(dataBrokerName: "Broker #7", lastRunDate: minusThreeHours), + .mock(dataBrokerName: "Broker #6", lastRunDate: minusThreeHours) ] let expected: [DBPUIScanProgress.ScannedBroker] = [ .mock("Broker #2", status: .inProgress), - .mock("Broker #7", status: .completed), .mock("Broker #6", status: .completed), + .mock("Broker #7", status: .completed), .mock("Broker #1", status: .completed), .mock("Broker #3", status: .inProgress) ] From 507162eb00c20100b42160589f43d5aabf4991cc Mon Sep 17 00:00:00 2001 From: Dax the Duck Date: Fri, 2 Aug 2024 12:36:04 +0000 Subject: [PATCH 02/32] Bump version to 1.100.0 (237) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index 927f03dec47..f36fd8bb8de 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 236 +CURRENT_PROJECT_VERSION = 237 From 1c2be8f45250f9652e9d1afca209a26cbe481d9a Mon Sep 17 00:00:00 2001 From: Dax the Duck Date: Fri, 2 Aug 2024 12:43:07 +0000 Subject: [PATCH 03/32] Bump version to 1.100.0 (238) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index f36fd8bb8de..773f6594824 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 237 +CURRENT_PROJECT_VERSION = 238 From 469d285180f05a10fc4320eda01d8ab3fbbd98bc Mon Sep 17 00:00:00 2001 From: Daniel Bernal Date: Fri, 2 Aug 2024 17:29:43 +0200 Subject: [PATCH 04/32] [DuckPlayer] 1. Move Extension to BSK and add Init Updates (#3055) Task/Issue URL: https://app.asana.com/0/1204099484721401/1207614229908937/f BSK PR: duckduckgo/BrowserServicesKit#921 Description: Steps to test this PR: Moves DuckPlayerURLextension to BSK Adds DuckPlayer init parameters for both script (FE requirement for future updates= --- DuckDuckGo.xcodeproj/project.pbxproj | 30 ++-- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../Common/Extensions/URLExtension.swift | 1 - .../DuckPlayerTabExtension.swift | 1 + DuckDuckGo/YoutubePlayer/DuckPlayer.swift | 55 +++++- .../DuckPlayerURLExtension.swift | 158 ------------------ .../YoutubeOverlayUserScript.swift | 17 +- .../YoutubePlayerNavigationHandler.swift | 1 + .../YoutubePlayerUserScript.swift | 2 +- .../DataBrokerProtection/Package.swift | 2 +- .../NetworkProtectionMac/Package.swift | 2 +- LocalPackages/SubscriptionUI/Package.swift | 2 +- .../DuckPlayerURLExtensionTests.swift | 142 ---------------- 13 files changed, 73 insertions(+), 344 deletions(-) delete mode 100644 DuckDuckGo/YoutubePlayer/DuckPlayerURLExtension.swift delete mode 100644 UnitTests/YoutubePlayer/DuckPlayerURLExtensionTests.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index edf1f8d9e71..58947dc20f3 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -278,7 +278,6 @@ 3706FA97293F65D500E42796 /* WindowDraggingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B693954526F04BEA0015B914 /* WindowDraggingView.swift */; }; 3706FA98293F65D500E42796 /* SecureVaultSorting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B1E6EEB27AB5E5100F51793 /* SecureVaultSorting.swift */; }; 3706FA99293F65D500E42796 /* PreferencesSidebarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37CD54C627F2FDD100F1F7B9 /* PreferencesSidebarModel.swift */; }; - 3706FA9A293F65D500E42796 /* DuckPlayerURLExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3767190128E724B2003A2A15 /* DuckPlayerURLExtension.swift */; }; 3706FA9D293F65D500E42796 /* PermissionState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6106BAC26A7BF390013B453 /* PermissionState.swift */; }; 3706FA9F293F65D500E42796 /* FeedbackPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 371C0A2827E33EDC0070591F /* FeedbackPresenter.swift */; }; 3706FAA0293F65D500E42796 /* UserAgent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14505A07256084EF00272CC6 /* UserAgent.swift */; }; @@ -872,7 +871,6 @@ 3706FE64293F661700E42796 /* DownloadListStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B693955C26F19CD70015B914 /* DownloadListStoreTests.swift */; }; 3706FE65293F661700E42796 /* ContentBlockingUpdatingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B610F2E527AA388100FCEBE9 /* ContentBlockingUpdatingTests.swift */; }; 3706FE67293F661700E42796 /* EncryptionMocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BA1A6F5258C4F9600F6F690 /* EncryptionMocks.swift */; }; - 3706FE68293F661700E42796 /* DuckPlayerURLExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376718FF28E58513003A2A15 /* DuckPlayerURLExtensionTests.swift */; }; 3706FE6A293F661700E42796 /* FirefoxKeyReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B2975982828285900187C4E /* FirefoxKeyReaderTests.swift */; }; 3706FE6B293F661700E42796 /* AppKitPrivateMethodsAvailabilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B698E5032908011E00A746A8 /* AppKitPrivateMethodsAvailabilityTests.swift */; }; 3706FE6D293F661700E42796 /* ChromiumBookmarksReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BB99D0C26FE1A83001E4761 /* ChromiumBookmarksReaderTests.swift */; }; @@ -1011,8 +1009,6 @@ 37534CA8281198CD002621E7 /* AdjacentItemEnumerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37534CA62811988E002621E7 /* AdjacentItemEnumerator.swift */; }; 376113CC2B29CD5B00E794BB /* CriticalPathsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 565E46DF2B2725DD0013AC2A /* CriticalPathsTests.swift */; }; 376705AF27EB488600DD8D76 /* RoundedSelectionRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B0511B3262CAA5A00F6079C /* RoundedSelectionRowView.swift */; }; - 3767190028E58513003A2A15 /* DuckPlayerURLExtensionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 376718FF28E58513003A2A15 /* DuckPlayerURLExtensionTests.swift */; }; - 3767190328E724D8003A2A15 /* DuckPlayerURLExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3767190128E724B2003A2A15 /* DuckPlayerURLExtension.swift */; }; 3768D8382C24BFF5004120AE /* RemoteMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3768D8372C24BFF5004120AE /* RemoteMessageView.swift */; }; 3768D8392C24BFF5004120AE /* RemoteMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3768D8372C24BFF5004120AE /* RemoteMessageView.swift */; }; 3768D83B2C24C0A8004120AE /* RemoteMessageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3768D83A2C24C0A8004120AE /* RemoteMessageViewModel.swift */; }; @@ -2588,6 +2584,8 @@ CBDD5DE429A6800300832877 /* MockConfigurationStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = CBDD5DE229A67F2700832877 /* MockConfigurationStore.swift */; }; D64A5FF82AEA5C2B00B6D6E7 /* HomeButtonMenuFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64A5FF72AEA5C2B00B6D6E7 /* HomeButtonMenuFactory.swift */; }; D64A5FF92AEA5C2B00B6D6E7 /* HomeButtonMenuFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64A5FF72AEA5C2B00B6D6E7 /* HomeButtonMenuFactory.swift */; }; + D6BC8AC62C5A95AA0025375B /* DuckPlayer in Frameworks */ = {isa = PBXBuildFile; productRef = D6BC8AC52C5A95AA0025375B /* DuckPlayer */; }; + D6BC8AC82C5A95B10025375B /* DuckPlayer in Frameworks */ = {isa = PBXBuildFile; productRef = D6BC8AC72C5A95B10025375B /* DuckPlayer */; }; EA0BA3A9272217E6002A0B6C /* ClickToLoadUserScript.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA0BA3A8272217E6002A0B6C /* ClickToLoadUserScript.swift */; }; EA18D1CA272F0DC8006DC101 /* social_images in Resources */ = {isa = PBXBuildFile; fileRef = EA18D1C9272F0DC8006DC101 /* social_images */; }; EA8AE76A279FBDB20078943E /* ClickToLoadTDSTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EA8AE769279FBDB20078943E /* ClickToLoadTDSTests.swift */; }; @@ -3105,8 +3103,6 @@ 376113C52B29BCD600E794BB /* SyncE2EUITests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SyncE2EUITests.xcconfig; sourceTree = ""; }; 376113D42B29CD5B00E794BB /* SyncE2EUITests App Store.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SyncE2EUITests App Store.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 376113D72B29D0F800E794BB /* SyncE2EUITestsAppStore.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = SyncE2EUITestsAppStore.xcconfig; sourceTree = ""; }; - 376718FF28E58513003A2A15 /* DuckPlayerURLExtensionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DuckPlayerURLExtensionTests.swift; sourceTree = ""; }; - 3767190128E724B2003A2A15 /* DuckPlayerURLExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DuckPlayerURLExtension.swift; sourceTree = ""; }; 3768D8372C24BFF5004120AE /* RemoteMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteMessageView.swift; sourceTree = ""; }; 3768D83A2C24C0A8004120AE /* RemoteMessageViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteMessageViewModel.swift; sourceTree = ""; }; 3768D83F2C29C1F1004120AE /* ActiveRemoteMessageModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActiveRemoteMessageModel.swift; sourceTree = ""; }; @@ -4328,6 +4324,7 @@ 85E2BBD02B8F534A00DBEC7A /* History in Frameworks */, 4BF97AD52B43C43F00EB4240 /* NetworkProtection in Frameworks */, 3739326529AE4B39009346AE /* DDGSync in Frameworks */, + D6BC8AC82C5A95B10025375B /* DuckPlayer in Frameworks */, 37DF000729F9C061002B7D3E /* SyncDataProviders in Frameworks */, 37BA812F29B3CD6E0053F1A3 /* SyncUI in Frameworks */, 3706FCAF293F65D500E42796 /* PrivacyDashboard in Frameworks */, @@ -4505,6 +4502,7 @@ B6F7128129F681EB00594A45 /* QuickLookUI.framework in Frameworks */, EE7295E32A545B9A008C0991 /* NetworkProtection in Frameworks */, 9807F645278CA16F00E1547B /* BrowserServicesKit in Frameworks */, + D6BC8AC62C5A95AA0025375B /* DuckPlayer in Frameworks */, 987799ED299998B1005D8EB6 /* Bookmarks in Frameworks */, 1E950E3F2912A10D0051A99B /* ContentBlocking in Frameworks */, 31A3A4E32B0C115F0021063C /* DataBrokerProtection in Frameworks */, @@ -4849,7 +4847,6 @@ isa = PBXGroup; children = ( 37F19A6928E2F2D000740DC6 /* DuckPlayer.swift */, - 3767190128E724B2003A2A15 /* DuckPlayerURLExtension.swift */, 31F28C5228C8EECA00119F70 /* DuckURLSchemeHandler.swift */, 315AA06F28CA5CC800200030 /* YoutubePlayerNavigationHandler.swift */, 31F28C4C28C8EEC500119F70 /* YoutubePlayerUserScript.swift */, @@ -4917,7 +4914,6 @@ isa = PBXGroup; children = ( 3714B1E828EDBAAB0056C57A /* DuckPlayerTests.swift */, - 376718FF28E58513003A2A15 /* DuckPlayerURLExtensionTests.swift */, 567DA94429E95C3F008AC5EE /* YoutubeOverlayUserScriptTests.swift */, ); path = YoutubePlayer; @@ -8617,6 +8613,7 @@ F198C71F2BD18D92000BF24D /* SwiftLintTool */, 7B2366852C09FACD002D393F /* VPNAppLauncher */, 371209242C232E6C003ADF3D /* RemoteMessaging */, + D6BC8AC72C5A95B10025375B /* DuckPlayer */, ); productName = DuckDuckGo; productReference = 3706FD05293F65D500E42796 /* DuckDuckGo App Store.app */; @@ -9021,6 +9018,7 @@ F198C71D2BD18D88000BF24D /* SwiftLintTool */, 7B2366832C09FAC2002D393F /* VPNAppLauncher */, 371209222C232E66003ADF3D /* RemoteMessaging */, + D6BC8AC52C5A95AA0025375B /* DuckPlayer */, ); productName = DuckDuckGo; productReference = AA585D7E248FD31100E9A3E2 /* DuckDuckGo.app */; @@ -9856,7 +9854,6 @@ 3706FA98293F65D500E42796 /* SecureVaultSorting.swift in Sources */, 1DEDB3652C19934C006B6D1B /* MoreOptionsMenuButton.swift in Sources */, 3706FA99293F65D500E42796 /* PreferencesSidebarModel.swift in Sources */, - 3706FA9A293F65D500E42796 /* DuckPlayerURLExtension.swift in Sources */, 3706FA9D293F65D500E42796 /* PermissionState.swift in Sources */, 3707C724294B5D2900682A9F /* StringExtension.swift in Sources */, 3706FA9F293F65D500E42796 /* FeedbackPresenter.swift in Sources */, @@ -10880,7 +10877,6 @@ 3706FE65293F661700E42796 /* ContentBlockingUpdatingTests.swift in Sources */, 3706FE67293F661700E42796 /* EncryptionMocks.swift in Sources */, 9F872D9E2B9058D000138637 /* Bookmarks+TabTests.swift in Sources */, - 3706FE68293F661700E42796 /* DuckPlayerURLExtensionTests.swift in Sources */, 3706FE6A293F661700E42796 /* FirefoxKeyReaderTests.swift in Sources */, 1DA860732BE3AE950027B813 /* DockPositionProviderTests.swift in Sources */, 3706FE6B293F661700E42796 /* AppKitPrivateMethodsAvailabilityTests.swift in Sources */, @@ -11299,7 +11295,6 @@ B693955326F04BEC0015B914 /* WindowDraggingView.swift in Sources */, 4B1E6EED27AB5E5100F51793 /* SecureVaultSorting.swift in Sources */, 37CD54CE27F2FDD100F1F7B9 /* PreferencesSidebarModel.swift in Sources */, - 3767190328E724D8003A2A15 /* DuckPlayerURLExtension.swift in Sources */, 1D43EB32292788C70065E5D6 /* BWEncryptionOutput.m in Sources */, 3707EC4A2C47E36A00B67CBE /* CloseButton.swift in Sources */, B6106BAD26A7BF390013B453 /* PermissionState.swift in Sources */, @@ -12337,7 +12332,6 @@ B610F2EB27AA8E4500FCEBE9 /* ContentBlockingUpdatingTests.swift in Sources */, 4BA1A6F6258C4F9600F6F690 /* EncryptionMocks.swift in Sources */, 56A054162C1C37B0007D8FAB /* CapturingOnboardingNavigation.swift in Sources */, - 3767190028E58513003A2A15 /* DuckPlayerURLExtensionTests.swift in Sources */, 9FBD847A2BB3EC3300220859 /* MockAttributionOriginProvider.swift in Sources */, 4B2975992828285900187C4E /* FirefoxKeyReaderTests.swift in Sources */, B698E5042908011E00A746A8 /* AppKitPrivateMethodsAvailabilityTests.swift in Sources */, @@ -13376,7 +13370,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 177.0.2; + version = 178.0.0; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { @@ -13958,6 +13952,16 @@ package = 9807F643278CA16F00E1547B /* XCRemoteSwiftPackageReference "BrowserServicesKit" */; productName = Configuration; }; + D6BC8AC52C5A95AA0025375B /* DuckPlayer */ = { + isa = XCSwiftPackageProductDependency; + package = 9807F643278CA16F00E1547B /* XCRemoteSwiftPackageReference "BrowserServicesKit" */; + productName = DuckPlayer; + }; + D6BC8AC72C5A95B10025375B /* DuckPlayer */ = { + isa = XCSwiftPackageProductDependency; + package = 9807F643278CA16F00E1547B /* XCRemoteSwiftPackageReference "BrowserServicesKit" */; + productName = DuckPlayer; + }; DC3F73D49B2D44464AFEFCD8 /* Subscription */ = { isa = XCSwiftPackageProductDependency; package = 3FFD51CF7C19ACBDB9687474 /* XCRemoteSwiftPackageReference "BrowserServicesKit" */; diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 03fada48d8e..2fa187fb002 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "ece50dc4a946de4d1d82c50a75a7dac101a7fb70", - "version" : "177.0.2" + "revision" : "ebad3db46e09913ac4c0e0c62085dcb40a6d6253", + "version" : "178.0.0" } }, { diff --git a/DuckDuckGo/Common/Extensions/URLExtension.swift b/DuckDuckGo/Common/Extensions/URLExtension.swift index 20658fc58c9..3164a215915 100644 --- a/DuckDuckGo/Common/Extensions/URLExtension.swift +++ b/DuckDuckGo/Common/Extensions/URLExtension.swift @@ -23,7 +23,6 @@ import Foundation extension URL.NavigationalScheme { - static let duck = URL.NavigationalScheme(rawValue: "duck") static let javascript = URL.NavigationalScheme(rawValue: "javascript") static var validSchemes: [URL.NavigationalScheme] { diff --git a/DuckDuckGo/Tab/TabExtensions/DuckPlayerTabExtension.swift b/DuckDuckGo/Tab/TabExtensions/DuckPlayerTabExtension.swift index 923e3edc787..a419a42dbe1 100644 --- a/DuckDuckGo/Tab/TabExtensions/DuckPlayerTabExtension.swift +++ b/DuckDuckGo/Tab/TabExtensions/DuckPlayerTabExtension.swift @@ -22,6 +22,7 @@ import ContentBlocking import Foundation import Navigation import PixelKit +import DuckPlayer protocol YoutubeScriptsProvider { var youtubeOverlayScript: YoutubeOverlayUserScript? { get } diff --git a/DuckDuckGo/YoutubePlayer/DuckPlayer.swift b/DuckDuckGo/YoutubePlayer/DuckPlayer.swift index c657ea76e4b..edfb674c87e 100644 --- a/DuckDuckGo/YoutubePlayer/DuckPlayer.swift +++ b/DuckDuckGo/YoutubePlayer/DuckPlayer.swift @@ -53,7 +53,7 @@ enum DuckPlayerMode: Equatable, Codable { } /// Values that the Frontend can use to determine the current state. -struct InitialSetupSettings: Codable { +struct InitialPlayerSettings: Codable { struct PlayerSettings: Codable { let pip: PIP let autoplay: Autoplay @@ -63,6 +63,14 @@ struct InitialSetupSettings: Codable { let state: State } + struct Platform: Codable { + let name: String + } + + enum Locale: String, Codable { + case en + } + struct Autoplay: Codable { let state: State } @@ -72,8 +80,20 @@ struct InitialSetupSettings: Codable { case disabled } + enum Environment: String, Codable { + case development + case production + } + let userValues: UserValues let settings: PlayerSettings + let platform: Platform + let environment: Environment + let locale: Locale +} + +struct InitialOverlaySettings: Codable { + let userValues: UserValues } // Values that the YouTube Overlays can use to determine the current state @@ -199,9 +219,15 @@ final class DuckPlayer { encodeUserValues() } - public func initialSetup(with webView: WKWebView?) -> (_ params: Any, _ message: UserScriptMessage) async -> Encodable? { + public func initialPlayerSetup(with webView: WKWebView?) -> (_ params: Any, _ message: UserScriptMessage) async -> Encodable? { return { _, _ in - return await self.encodedSettings(with: webView) + return await self.encodedPlayerSettings(with: webView) + } + } + + public func initialOverlaySetup(with webView: WKWebView?) -> (_ params: Any, _ message: UserScriptMessage) async -> Encodable? { + return { _, _ in + return await self.encodedOverlaySettings(with: webView) } } @@ -213,7 +239,7 @@ final class DuckPlayer { } @MainActor - private func encodedSettings(with webView: WKWebView?) async -> InitialSetupSettings { + private func encodedPlayerSettings(with webView: WKWebView?) async -> InitialPlayerSettings { var isPiPEnabled = webView?.configuration.preferences[.allowsPictureInPictureMediaPlayback] == true var isAutoplayEnabled = DuckPlayerPreferences.shared.duckPlayerAutoplay @@ -230,13 +256,26 @@ final class DuckPlayer { isPiPEnabled = false } - let pip = InitialSetupSettings.PIP(state: isPiPEnabled ? .enabled : .disabled) - let autoplay = InitialSetupSettings.Autoplay(state: isAutoplayEnabled ? .enabled : .disabled) + let pip = InitialPlayerSettings.PIP(state: isPiPEnabled ? .enabled : .disabled) + let autoplay = InitialPlayerSettings.Autoplay(state: isAutoplayEnabled ? .enabled : .disabled) + let platform = InitialPlayerSettings.Platform(name: "ios") + let environment = InitialPlayerSettings.Environment.development + let locale = InitialPlayerSettings.Locale.en + let playerSettings = InitialPlayerSettings.PlayerSettings(pip: pip, autoplay: autoplay) + let userValues = encodeUserValues() + + return InitialPlayerSettings(userValues: userValues, + settings: playerSettings, + platform: platform, + environment: environment, + locale: locale) + } - let playerSettings = InitialSetupSettings.PlayerSettings(pip: pip, autoplay: autoplay) + @MainActor + private func encodedOverlaySettings(with webView: WKWebView?) async -> InitialOverlaySettings { let userValues = encodeUserValues() - return InitialSetupSettings(userValues: userValues, settings: playerSettings) + return InitialOverlaySettings(userValues: userValues) } // MARK: - Private diff --git a/DuckDuckGo/YoutubePlayer/DuckPlayerURLExtension.swift b/DuckDuckGo/YoutubePlayer/DuckPlayerURLExtension.swift deleted file mode 100644 index 585ad99b087..00000000000 --- a/DuckDuckGo/YoutubePlayer/DuckPlayerURLExtension.swift +++ /dev/null @@ -1,158 +0,0 @@ -// -// DuckPlayerURLExtension.swift -// -// Copyright © 2022 DuckDuckGo. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -extension URL { - /** - * Returns the actual URL of the Private Player page. - * - * Depending on the use of simulated requests, it's either the custom scheme URL - * (without simulated requests, macOS <12), or youtube-nocookie.com URL (macOS 12 and newer). - */ - static func effectiveDuckPlayer(_ videoID: String, timestamp: String? = nil) -> URL { - if DuckPlayer.usesSimulatedRequests { - return .youtubeNoCookie(videoID, timestamp: timestamp) - } - return .duckPlayer(videoID, timestamp: timestamp) - } - - static func duckPlayer(_ videoID: String, timestamp: String? = nil) -> URL { - let url = "\(NavigationalScheme.duck.rawValue)://player/\(videoID)".url! - return url.addingTimestamp(timestamp) - } - - static func youtubeNoCookie(_ videoID: String, timestamp: String? = nil) -> URL { - let url = "https://www.youtube-nocookie.com/embed/\(videoID)".url! - return url.addingTimestamp(timestamp) - } - - static func youtube(_ videoID: String, timestamp: String? = nil) -> URL { - let url = "https://www.youtube.com/watch?v=\(videoID)".url! - return url.addingTimestamp(timestamp) - } - - /** - * Returns true if a URL represents a Private Player URL. - * - * It primarily checks for `duck://player/` URL, but on macOS 12 and above (when using simulated requests), - * the Duck Scheme URL is eventually replaced by `www.youtube-nocookie.com/embed/VIDEOID` URL so this - * is checked too and this function returns `true` if any of the two is true on macOS 12. - */ - var isDuckPlayer: Bool { - let isPrivatePlayer = isDuckURLScheme && host == DuckPlayer.duckPlayerHost - if DuckPlayer.usesSimulatedRequests { - return isPrivatePlayer || isYoutubeNoCookie - } else { - return isPrivatePlayer - } - } - - /// Returns true only if the URL represents a playlist itself, i.e. doesn't have `index` query parameter - var isYoutubePlaylist: Bool { - guard isYoutubeWatch, let components = URLComponents(url: self, resolvingAgainstBaseURL: false) else { - return false - } - - let isPlaylistURL = components.queryItems?.contains(where: { $0.name == "list" }) == true && - components.queryItems?.contains(where: { $0.name == "v" }) == true && - components.queryItems?.contains(where: { $0.name == "index" }) == false - - return isPlaylistURL - } - - /// Returns true if the URL represents a YouTube video, but not the playlist (playlists are not supported by Private Player) - var isYoutubeVideo: Bool { - isYoutubeWatch && !isYoutubePlaylist - } - - /** - * Returns true if the URL represents a YouTube video recommendation. - * - * Recommendations are shown at the end of the embedded video or while it's paused. - */ - var isYoutubeVideoRecommendation: Bool { - guard isYoutubeVideo, - let components = URLComponents(url: self, resolvingAgainstBaseURL: false), - let featureQueryParameter = components.queryItems?.first(where: { $0.name == "feature" })?.value - else { - return false - } - - let recommendationFeatures = [ "emb_rel_end", "emb_rel_pause" ] - - return recommendationFeatures.contains(featureQueryParameter) - } - - /// Attempts extracting video ID and timestamp from the URL. Works with all types of YouTube URLs. - var youtubeVideoParams: (videoID: String, timestamp: String?)? { - if isDuckURLScheme { - guard let components = URLComponents(string: absoluteString) else { - return nil - } - let unsafeVideoID = components.path - let timestamp = components.queryItems?.first(where: { $0.name == "t" })?.value - return (unsafeVideoID.removingCharacters(in: .youtubeVideoIDNotAllowed), timestamp) - } - - if isDuckPlayer { - let unsafeVideoID = lastPathComponent - let timestamp = getParameter(named: "t") - return (unsafeVideoID.removingCharacters(in: .youtubeVideoIDNotAllowed), timestamp) - } - - guard isYoutubeVideo, - let components = URLComponents(url: self, resolvingAgainstBaseURL: false), - let unsafeVideoID = components.queryItems?.first(where: { $0.name == "v" })?.value - else { - return nil - } - - let timestamp = components.queryItems?.first(where: { $0.name == "t" })?.value - return (unsafeVideoID.removingCharacters(in: .youtubeVideoIDNotAllowed), timestamp) - } - - var youtubeVideoID: String? { - youtubeVideoParams?.videoID - } - - // MARK: - Private - - private var isYoutubeNoCookie: Bool { - host == "www.youtube-nocookie.com" && pathComponents.count == 3 && pathComponents[safe: 1] == "embed" - } - - private var isYoutubeWatch: Bool { - guard let host else { return false } - return host.contains("youtube.com") && path == "/watch" - } - - private func addingTimestamp(_ timestamp: String?) -> URL { - guard let timestamp = timestamp, - let regex = try? NSRegularExpression(pattern: "^(\\d+[smh]?)+$"), - timestamp.matches(regex) - else { - return self - } - return appendingParameter(name: "t", value: timestamp) - } -} - -extension CharacterSet { - static let youtubeVideoIDNotAllowed = CharacterSet(charactersIn: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_").inverted -} diff --git a/DuckDuckGo/YoutubePlayer/YoutubeOverlayUserScript.swift b/DuckDuckGo/YoutubePlayer/YoutubeOverlayUserScript.swift index afe0e5a2459..79ba756c2d9 100644 --- a/DuckDuckGo/YoutubePlayer/YoutubeOverlayUserScript.swift +++ b/DuckDuckGo/YoutubePlayer/YoutubeOverlayUserScript.swift @@ -84,7 +84,7 @@ final class YoutubeOverlayUserScript: NSObject, Subfeature { case .getUserValues: return DuckPlayer.shared.handleGetUserValues case .initialSetup: - return handleInitialSetup + return DuckPlayer.shared.initialOverlaySetup(with: webView) case .openDuckPlayer: return handleOpenDuckPlayer case .sendDuckPlayerPixel: @@ -119,21 +119,6 @@ final class YoutubeOverlayUserScript: NSObject, Subfeature { return nil } - private func handleInitialSetup(params: Any, message: UserScriptMessage) -> Encodable? { - encodeInitialSetup() - } - - private func encodeInitialSetup() -> OverlaysInitialSettings { - let userValues = UserValues( - duckPlayerMode: duckPlayerPreferences.duckPlayerMode, - overlayInteracted: duckPlayerPreferences.youtubeOverlayInteracted - ) - - return OverlaysInitialSettings( - userValues: userValues - ) - } - // MARK: - UserValuesNotification struct UserValuesNotification: Encodable { diff --git a/DuckDuckGo/YoutubePlayer/YoutubePlayerNavigationHandler.swift b/DuckDuckGo/YoutubePlayer/YoutubePlayerNavigationHandler.swift index 6c62c9df631..8bdabb4e78d 100644 --- a/DuckDuckGo/YoutubePlayer/YoutubePlayerNavigationHandler.swift +++ b/DuckDuckGo/YoutubePlayer/YoutubePlayerNavigationHandler.swift @@ -18,6 +18,7 @@ import Foundation import ContentScopeScripts +import DuckPlayer struct YoutubePlayerNavigationHandler { diff --git a/DuckDuckGo/YoutubePlayer/YoutubePlayerUserScript.swift b/DuckDuckGo/YoutubePlayer/YoutubePlayerUserScript.swift index 2a0af3883ca..64ebf4c2229 100644 --- a/DuckDuckGo/YoutubePlayer/YoutubePlayerUserScript.swift +++ b/DuckDuckGo/YoutubePlayer/YoutubePlayerUserScript.swift @@ -55,7 +55,7 @@ final class YoutubePlayerUserScript: NSObject, Subfeature { case .setUserValues: return DuckPlayer.shared.handleSetUserValuesMessage(from: .duckPlayer) case .initialSetup: - return DuckPlayer.shared.initialSetup(with: webView) + return DuckPlayer.shared.initialPlayerSetup(with: webView) default: assertionFailure("YoutubePlayerUserScript: Failed to parse User Script message: \(methodName)") return nil diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index 2bca97612db..6785bcd4980 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "177.0.2"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "178.0.0"), .package(path: "../SwiftUIExtensions"), .package(path: "../XPCHelper"), ], diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index ab6e52091c5..bb1cbb7e170 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -32,7 +32,7 @@ let package = Package( .library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "177.0.2"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "178.0.0"), .package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"), .package(path: "../AppLauncher"), .package(path: "../UDSHelper"), diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index c23fe2a0fea..c87fc52740f 100644 --- a/LocalPackages/SubscriptionUI/Package.swift +++ b/LocalPackages/SubscriptionUI/Package.swift @@ -12,7 +12,7 @@ let package = Package( targets: ["SubscriptionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "177.0.2"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "178.0.0"), .package(path: "../SwiftUIExtensions") ], targets: [ diff --git a/UnitTests/YoutubePlayer/DuckPlayerURLExtensionTests.swift b/UnitTests/YoutubePlayer/DuckPlayerURLExtensionTests.swift deleted file mode 100644 index d4e004c0c67..00000000000 --- a/UnitTests/YoutubePlayer/DuckPlayerURLExtensionTests.swift +++ /dev/null @@ -1,142 +0,0 @@ -// -// DuckPlayerURLExtensionTests.swift -// -// Copyright © 2022 DuckDuckGo. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import XCTest -import os.log -@testable import DuckDuckGo_Privacy_Browser - -final class DuckPlayerURLExtensionTests: XCTestCase { - - func testIsDuckPlayerScheme() { - XCTAssertTrue("duck:player/abcdef12345".url!.isDuckURLScheme) - XCTAssertTrue("duck://player/abcdef12345".url!.isDuckURLScheme) - XCTAssertTrue("duck://player/abcdef".url!.isDuckURLScheme) - XCTAssertTrue("duck://player/12345".url!.isDuckURLScheme) - XCTAssertFalse("http://duckplayer/abcdef12345".url!.isDuckURLScheme) - XCTAssertFalse("https://www.youtube.com/watch?v=abcdef12345".url!.isDuckURLScheme) - XCTAssertFalse("https://www.youtube-nocookie.com/embed/abcdef12345".url!.isDuckURLScheme) - } - - func testIsDuckPlayer() { - XCTAssertTrue("https://www.youtube-nocookie.com/embed/abcdef12345".url!.isDuckPlayer) - XCTAssertTrue("https://www.youtube-nocookie.com/embed/abcdef12345?t=23s".url!.isDuckPlayer) - - XCTAssertFalse("https://www.youtube-nocookie.com/embed".url!.isDuckPlayer) - XCTAssertFalse("https://www.youtube-nocookie.com/embed?t=23s".url!.isDuckPlayer) - - XCTAssertTrue("duck://player/abcdef12345".url!.isDuckPlayer) - XCTAssertFalse("https://www.youtube.com/watch?v=abcdef12345".url!.isDuckPlayer) - XCTAssertFalse("https://duckduckgo.com".url!.isDuckPlayer) - } - - func testIsYoutubePlaylist() { - XCTAssertTrue("https://www.youtube.com/watch?v=abcdef12345&list=abcdefgh12345678".url!.isYoutubePlaylist) - XCTAssertTrue("https://www.youtube.com/watch?list=abcdefgh12345678&v=abcdef12345".url!.isYoutubePlaylist) - - XCTAssertFalse("https://duckduckgo.com/watch?v=abcdef12345&list=abcdefgh12345678".url!.isYoutubePlaylist) - XCTAssertFalse("https://www.youtube.com/watch?list=abcdefgh12345678".url!.isYoutubePlaylist) - XCTAssertFalse("https://www.youtube.com/watch?v=abcdef12345&list=abcdefgh12345678&index=1".url!.isYoutubePlaylist) - } - - func testIsYoutubeVideo() { - XCTAssertTrue("https://www.youtube.com/watch?v=abcdef12345".url!.isYoutubeVideo) - XCTAssertTrue("https://www.youtube.com/watch?v=abcdef12345&list=abcdefgh12345678&index=1".url!.isYoutubeVideo) - XCTAssertTrue("https://www.youtube.com/watch?v=abcdef12345&t=5m".url!.isYoutubeVideo) - - XCTAssertFalse("https://www.youtube.com/watch?v=abcdef12345&list=abcdefgh12345678".url!.isYoutubeVideo) - XCTAssertFalse("https://duckduckgo.com/watch?v=abcdef12345".url!.isYoutubeVideo) - } - - func testYoutubeVideoParamsFromDuckPlayerURL() { - let params = "duck://player/abcdef12345".url!.youtubeVideoParams - XCTAssertEqual(params?.videoID, "abcdef12345") - XCTAssertEqual(params?.timestamp, nil) - - let paramsWithTimestamp = "duck://player/abcdef12345?t=23s".url!.youtubeVideoParams - XCTAssertEqual(paramsWithTimestamp?.videoID, "abcdef12345") - XCTAssertEqual(paramsWithTimestamp?.timestamp, "23s") - } - - func testYoutubeVideoParamsFromYoutubeURL() { - let params = "https://www.youtube.com/watch?v=abcdef12345".url!.youtubeVideoParams - XCTAssertEqual(params?.videoID, "abcdef12345") - XCTAssertEqual(params?.timestamp, nil) - - let paramsWithTimestamp = "https://www.youtube.com/watch?v=abcdef12345&t=23s".url!.youtubeVideoParams - XCTAssertEqual(paramsWithTimestamp?.videoID, "abcdef12345") - XCTAssertEqual(paramsWithTimestamp?.timestamp, "23s") - - let paramsWithTimestampWithoutUnits = "https://www.youtube.com/watch?t=102&v=abcdef12345&feature=youtu.be".url!.youtubeVideoParams - XCTAssertEqual(paramsWithTimestampWithoutUnits?.videoID, "abcdef12345") - XCTAssertEqual(paramsWithTimestampWithoutUnits?.timestamp, "102") - } - - func testYoutubeVideoParamsFromYoutubeNocookieURL() { - let params = "https://www.youtube-nocookie.com/embed/abcdef12345".url!.youtubeVideoParams - XCTAssertEqual(params?.videoID, "abcdef12345") - XCTAssertEqual(params?.timestamp, nil) - - let paramsWithTimestamp = "https://www.youtube-nocookie.com/embed/abcdef12345?t=23s".url!.youtubeVideoParams - XCTAssertEqual(paramsWithTimestamp?.videoID, "abcdef12345") - XCTAssertEqual(paramsWithTimestamp?.timestamp, "23s") - } - - func testYoutubeVideoID() { - XCTAssertEqual(URL.youtube("abcdef12345", timestamp: nil).youtubeVideoID, "abcdef12345") - XCTAssertEqual(URL.youtube("abcd
ef12345", timestamp: nil).youtubeVideoID, "abcdbref12345") - - XCTAssertNil("https://duck.com".url?.youtubeVideoID) - } - - func testDuckPlayerURLTimestampValidation() { - XCTAssertEqual(URL.duckPlayer("abcdef12345", timestamp: nil).absoluteString, "duck://player/abcdef12345") - XCTAssertEqual(URL.duckPlayer("abcdef12345", timestamp: "23s").absoluteString, "duck://player/abcdef12345?t=23s") - XCTAssertEqual(URL.duckPlayer("abcdef12345", timestamp: "5m5s").absoluteString, "duck://player/abcdef12345?t=5m5s") - XCTAssertEqual(URL.duckPlayer("abcdef12345", timestamp: "12h400m100s").absoluteString, "duck://player/abcdef12345?t=12h400m100s") - XCTAssertEqual(URL.duckPlayer("abcdef12345", timestamp: "12h2s2h").absoluteString, "duck://player/abcdef12345?t=12h2s2h") - XCTAssertEqual(URL.duckPlayer("abcdef12345", timestamp: "5m5m5m").absoluteString, "duck://player/abcdef12345?t=5m5m5m") - - XCTAssertEqual(URL.duckPlayer("abcdef12345", timestamp: "5").absoluteString, "duck://player/abcdef12345?t=5") - XCTAssertEqual(URL.duckPlayer("abcdef12345", timestamp: "10d").absoluteString, "duck://player/abcdef12345") - } - - func testYoutubeURLTimestampValidation() { - XCTAssertEqual(URL.youtube("abcdef12345", timestamp: nil).absoluteString, "https://www.youtube.com/watch?v=abcdef12345") - XCTAssertEqual(URL.youtube("abcdef12345", timestamp: "23s").absoluteString, "https://www.youtube.com/watch?v=abcdef12345&t=23s") - XCTAssertEqual(URL.youtube("abcdef12345", timestamp: "5m5s").absoluteString, "https://www.youtube.com/watch?v=abcdef12345&t=5m5s") - XCTAssertEqual(URL.youtube("abcdef12345", timestamp: "12h400m100s").absoluteString, "https://www.youtube.com/watch?v=abcdef12345&t=12h400m100s") - XCTAssertEqual(URL.youtube("abcdef12345", timestamp: "12h2s2h").absoluteString, "https://www.youtube.com/watch?v=abcdef12345&t=12h2s2h") - XCTAssertEqual(URL.youtube("abcdef12345", timestamp: "5m5m5m").absoluteString, "https://www.youtube.com/watch?v=abcdef12345&t=5m5m5m") - - XCTAssertEqual(URL.youtube("abcdef12345", timestamp: "5").absoluteString, "https://www.youtube.com/watch?v=abcdef12345&t=5") - XCTAssertEqual(URL.youtube("abcdef12345", timestamp: "10d").absoluteString, "https://www.youtube.com/watch?v=abcdef12345") - } - - func testYoutubeNoCookieURLTimestampValidation() { - XCTAssertEqual(URL.youtubeNoCookie("abcdef12345", timestamp: nil).absoluteString, "https://www.youtube-nocookie.com/embed/abcdef12345") - XCTAssertEqual(URL.youtubeNoCookie("abcdef12345", timestamp: "23s").absoluteString, "https://www.youtube-nocookie.com/embed/abcdef12345?t=23s") - XCTAssertEqual(URL.youtubeNoCookie("abcdef12345", timestamp: "5m5s").absoluteString, "https://www.youtube-nocookie.com/embed/abcdef12345?t=5m5s") - XCTAssertEqual(URL.youtubeNoCookie("abcdef12345", timestamp: "12h400m100s").absoluteString, "https://www.youtube-nocookie.com/embed/abcdef12345?t=12h400m100s") - XCTAssertEqual(URL.youtubeNoCookie("abcdef12345", timestamp: "12h2s2h").absoluteString, "https://www.youtube-nocookie.com/embed/abcdef12345?t=12h2s2h") - XCTAssertEqual(URL.youtubeNoCookie("abcdef12345", timestamp: "5m5m5m").absoluteString, "https://www.youtube-nocookie.com/embed/abcdef12345?t=5m5m5m") - - XCTAssertEqual(URL.youtubeNoCookie("abcdef12345", timestamp: "5").absoluteString, "https://www.youtube-nocookie.com/embed/abcdef12345?t=5") - XCTAssertEqual(URL.youtubeNoCookie("abcdef12345", timestamp: "10d").absoluteString, "https://www.youtube-nocookie.com/embed/abcdef12345") - } - -} From 9e399dc3cf4d4b402ee5b270e6d711ef0ca35e8a Mon Sep 17 00:00:00 2001 From: Dax Mobile <44842493+daxmobile@users.noreply.github.com> Date: Fri, 2 Aug 2024 13:04:59 -0400 Subject: [PATCH 05/32] Update autoconsent to v10.13.0 (#3063) Task/Issue URL: https://app.asana.com/0/1207964054389971/1207964054389971 Autoconsent Release: https://github.com/duckduckgo/autoconsent/releases/tag/v10.13.0 ## Description Updates Autoconsent to version [v10.13.0](https://github.com/duckduckgo/autoconsent/releases/tag/v10.13.0). --- DuckDuckGo/Autoconsent/autoconsent-bundle.js | 2 +- package-lock.json | 27 +++++++++++++++++--- package.json | 2 +- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/DuckDuckGo/Autoconsent/autoconsent-bundle.js b/DuckDuckGo/Autoconsent/autoconsent-bundle.js index 200fd20d225..841fda7b495 100644 --- a/DuckDuckGo/Autoconsent/autoconsent-bundle.js +++ b/DuckDuckGo/Autoconsent/autoconsent-bundle.js @@ -1 +1 @@ -!function(){"use strict";var e=class e{static setBase(t){e.base=t}static findElement(t,o=null,c=!1){let i=null;return i=null!=o?Array.from(o.querySelectorAll(t.selector)):null!=e.base?Array.from(e.base.querySelectorAll(t.selector)):Array.from(document.querySelectorAll(t.selector)),null!=t.textFilter&&(i=i.filter((e=>{const o=e.textContent.toLowerCase();if(Array.isArray(t.textFilter)){let e=!1;for(const c of t.textFilter)if(-1!==o.indexOf(c.toLowerCase())){e=!0;break}return e}if(null!=t.textFilter)return-1!==o.indexOf(t.textFilter.toLowerCase())}))),null!=t.styleFilters&&(i=i.filter((e=>{const o=window.getComputedStyle(e);let c=!0;for(const e of t.styleFilters){const t=o[e.option];c=e.negated?c&&t!==e.value:c&&t===e.value}return c}))),null!=t.displayFilter&&(i=i.filter((e=>t.displayFilter?0!==e.offsetHeight:0===e.offsetHeight))),null!=t.iframeFilter&&(i=i.filter((()=>t.iframeFilter?window.location!==window.parent.location:window.location===window.parent.location))),null!=t.childFilter&&(i=i.filter((o=>{const c=e.base;e.setBase(o);const i=e.find(t.childFilter);return e.setBase(c),null!=i.target}))),c?i:(i.length>1&&console.warn("Multiple possible targets: ",i,t,o),i[0])}static find(t,o=!1){const c=[];if(null!=t.parent){const i=e.findElement(t.parent,null,o);if(null!=i){if(i instanceof Array)return i.forEach((i=>{const n=e.findElement(t.target,i,o);n instanceof Array?n.forEach((e=>{c.push({parent:i,target:e})})):c.push({parent:i,target:n})})),c;{const n=e.findElement(t.target,i,o);n instanceof Array?n.forEach((e=>{c.push({parent:i,target:e})})):c.push({parent:i,target:n})}}}else{const i=e.findElement(t.target,null,o);i instanceof Array?i.forEach((e=>{c.push({parent:null,target:e})})):c.push({parent:null,target:i})}return 0===c.length&&c.push({parent:null,target:null}),o?c:(1!==c.length&&console.warn("Multiple results found, even though multiple false",c),c[0])}};e.base=null;var t=e;function o(e){const o=t.find(e);return"css"===e.type?!!o.target:"checkbox"===e.type?!!o.target&&o.target.checked:void 0}async function c(e,n){switch(e.type){case"click":return async function(e){const o=t.find(e);null!=o.target&&o.target.click();return i(0)}(e);case"list":return async function(e,t){for(const o of e.actions)await c(o,t)}(e,n);case"consent":return async function(e,t){for(const i of e.consents){const e=-1!==t.indexOf(i.type);if(i.matcher&&i.toggleAction){o(i.matcher)!==e&&await c(i.toggleAction)}else e?await c(i.trueAction):await c(i.falseAction)}}(e,n);case"ifcss":return async function(e,o){const i=t.find(e);i.target?e.falseAction&&await c(e.falseAction,o):e.trueAction&&await c(e.trueAction,o)}(e,n);case"waitcss":return async function(e){await new Promise((o=>{let c=e.retries||10;const i=e.waitTime||250,n=()=>{const a=t.find(e);(e.negated&&a.target||!e.negated&&!a.target)&&c>0?(c-=1,setTimeout(n,i)):o()};n()}))}(e);case"foreach":return async function(e,o){const i=t.find(e,!0),n=t.base;for(const n of i)n.target&&(t.setBase(n.target),await c(e.action,o));t.setBase(n)}(e,n);case"hide":return async function(e){const o=t.find(e);o.target&&o.target.classList.add("Autoconsent-Hidden")}(e);case"slide":return async function(e){const o=t.find(e),c=t.find(e.dragTarget);if(o.target){const e=o.target.getBoundingClientRect(),t=c.target.getBoundingClientRect();let i=t.top-e.top,n=t.left-e.left;"y"===this.config.axis.toLowerCase()&&(n=0),"x"===this.config.axis.toLowerCase()&&(i=0);const a=window.screenX+e.left+e.width/2,s=window.screenY+e.top+e.height/2,r=e.left+e.width/2,l=e.top+e.height/2,p=document.createEvent("MouseEvents");p.initMouseEvent("mousedown",!0,!0,window,0,a,s,r,l,!1,!1,!1,!1,0,o.target);const d=document.createEvent("MouseEvents");d.initMouseEvent("mousemove",!0,!0,window,0,a+n,s+i,r+n,l+i,!1,!1,!1,!1,0,o.target);const u=document.createEvent("MouseEvents");u.initMouseEvent("mouseup",!0,!0,window,0,a+n,s+i,r+n,l+i,!1,!1,!1,!1,0,o.target),o.target.dispatchEvent(p),await this.waitTimeout(10),o.target.dispatchEvent(d),await this.waitTimeout(10),o.target.dispatchEvent(u)}}(e);case"close":return async function(){window.close()}();case"wait":return async function(e){await i(e.waitTime)}(e);case"eval":return async function(e){return console.log("eval!",e.code),new Promise((t=>{try{e.async?(window.eval(e.code),setTimeout((()=>{t(window.eval("window.__consentCheckResult"))}),e.timeout||250)):t(window.eval(e.code))}catch(o){console.warn("eval error",o,e.code),t(!1)}}))}(e);default:throw"Unknown action type: "+e.type}}function i(e){return new Promise((t=>{setTimeout((()=>{t()}),e)}))}function n(){return crypto&&void 0!==crypto.randomUUID?crypto.randomUUID():Math.random().toString()}var a={pending:new Map,sendContentMessage:null};function s(e,t){const o=n();a.sendContentMessage({type:"eval",id:o,code:e,snippetId:t});const c=new class{constructor(e,t=1e3){this.id=e,this.promise=new Promise(((e,t)=>{this.resolve=e,this.reject=t})),this.timer=window.setTimeout((()=>{this.reject(new Error("timeout"))}),t)}}(o);return a.pending.set(c.id,c),c.promise}var r={EVAL_0:()=>console.log(1),EVAL_CONSENTMANAGER_1:()=>window.__cmp&&"object"==typeof __cmp("getCMPData"),EVAL_CONSENTMANAGER_2:()=>!__cmp("consentStatus").userChoiceExists,EVAL_CONSENTMANAGER_3:()=>__cmp("setConsent",0),EVAL_CONSENTMANAGER_4:()=>__cmp("setConsent",1),EVAL_CONSENTMANAGER_5:()=>__cmp("consentStatus").userChoiceExists,EVAL_COOKIEBOT_1:()=>!!window.Cookiebot,EVAL_COOKIEBOT_2:()=>!window.Cookiebot.hasResponse&&!0===window.Cookiebot.dialog?.visible,EVAL_COOKIEBOT_3:()=>window.Cookiebot.withdraw()||!0,EVAL_COOKIEBOT_4:()=>window.Cookiebot.hide()||!0,EVAL_COOKIEBOT_5:()=>!0===window.Cookiebot.declined,EVAL_KLARO_1:()=>{const e=globalThis.klaroConfig||globalThis.klaro?.getManager&&globalThis.klaro.getManager().config;if(!e)return!0;const t=(e.services||e.apps).filter((e=>!e.required)).map((e=>e.name));if(klaro&&klaro.getManager){const e=klaro.getManager();return t.every((t=>!e.consents[t]))}if(klaroConfig&&"cookie"===klaroConfig.storageMethod){const e=klaroConfig.cookieName||klaroConfig.storageName,o=JSON.parse(decodeURIComponent(document.cookie.split(";").find((t=>t.trim().startsWith(e))).split("=")[1]));return Object.keys(o).filter((e=>t.includes(e))).every((e=>!1===o[e]))}},EVAL_KLARO_OPEN_POPUP:()=>{klaro.show(void 0,!0)},EVAL_KLARO_TRY_API_OPT_OUT:()=>{if(window.klaro&&"function"==typeof klaro.show&&"function"==typeof klaro.getManager)try{return klaro.getManager().changeAll(!1),klaro.getManager().saveAndApplyConsents(),!0}catch(e){return console.warn(e),!1}return!1},EVAL_ONETRUST_1:()=>window.OnetrustActiveGroups.split(",").filter((e=>e.length>0)).length<=1,EVAL_TRUSTARC_TOP:()=>window&&window.truste&&"0"===window.truste.eu.bindMap.prefCookie,EVAL_TRUSTARC_FRAME_TEST:()=>window&&window.QueryString&&"0"===window.QueryString.preferences,EVAL_TRUSTARC_FRAME_GTM:()=>window&&window.QueryString&&"1"===window.QueryString.gtm,EVAL_ADROLL_0:()=>!document.cookie.includes("__adroll_fpc"),EVAL_ALMACMP_0:()=>document.cookie.includes('"name":"Google","consent":false'),EVAL_AFFINITY_SERIF_COM_0:()=>document.cookie.includes("serif_manage_cookies_viewed")&&!document.cookie.includes("serif_allow_analytics"),EVAL_ARBEITSAGENTUR_TEST:()=>document.cookie.includes("cookie_consent=denied"),EVAL_AXEPTIO_0:()=>document.cookie.includes("axeptio_authorized_vendors=%2C%2C"),EVAL_BAHN_TEST:()=>1===utag.gdpr.getSelectedCategories().length,EVAL_BING_0:()=>document.cookie.includes("AL=0")&&document.cookie.includes("AD=0")&&document.cookie.includes("SM=0"),EVAL_BLOCKSY_0:()=>document.cookie.includes("blocksy_cookies_consent_accepted=no"),EVAL_BORLABS_0:()=>!JSON.parse(decodeURIComponent(document.cookie.split(";").find((e=>-1!==e.indexOf("borlabs-cookie"))).split("=",2)[1])).consents.statistics,EVAL_BUNDESREGIERUNG_DE_0:()=>document.cookie.match("cookie-allow-tracking=0"),EVAL_CANVA_0:()=>!document.cookie.includes("gtm_fpc_engagement_event"),EVAL_CC_BANNER2_0:()=>!!document.cookie.match(/sncc=[^;]+D%3Dtrue/),EVAL_CLICKIO_0:()=>document.cookie.includes("__lxG__consent__v2_daisybit="),EVAL_CLINCH_0:()=>document.cookie.includes("ctc_rejected=1"),EVAL_COOKIECONSENT2_TEST:()=>document.cookie.includes("cc_cookie="),EVAL_COOKIECONSENT3_TEST:()=>document.cookie.includes("cc_cookie="),EVAL_COINBASE_0:()=>JSON.parse(decodeURIComponent(document.cookie.match(/cm_(eu|default)_preferences=([0-9a-zA-Z\\{\\}\\[\\]%:]*);?/)[2])).consent.length<=1,EVAL_COMPLIANZ_BANNER_0:()=>document.cookie.includes("cmplz_banner-status=dismissed"),EVAL_COOKIE_LAW_INFO_0:()=>CLI.disableAllCookies()||CLI.reject_close()||!0,EVAL_COOKIE_LAW_INFO_1:()=>-1===document.cookie.indexOf("cookielawinfo-checkbox-non-necessary=yes"),EVAL_COOKIE_LAW_INFO_DETECT:()=>!!window.CLI,EVAL_COOKIE_MANAGER_POPUP_0:()=>!1===JSON.parse(document.cookie.split(";").find((e=>e.trim().startsWith("CookieLevel"))).split("=")[1]).social,EVAL_COOKIEALERT_0:()=>document.querySelector("body").removeAttribute("style")||!0,EVAL_COOKIEALERT_1:()=>document.querySelector("body").removeAttribute("style")||!0,EVAL_COOKIEALERT_2:()=>!0===window.CookieConsent.declined,EVAL_COOKIEFIRST_0:()=>{return!1===(e=JSON.parse(decodeURIComponent(document.cookie.split(";").find((e=>-1!==e.indexOf("cookiefirst"))).trim()).split("=")[1])).performance&&!1===e.functional&&!1===e.advertising;var e},EVAL_COOKIEFIRST_1:()=>document.querySelectorAll("button[data-cookiefirst-accent-color=true][role=checkbox]:not([disabled])").forEach((e=>"true"==e.getAttribute("aria-checked")&&e.click()))||!0,EVAL_COOKIEINFORMATION_0:()=>CookieInformation.declineAllCategories()||!0,EVAL_COOKIEINFORMATION_1:()=>CookieInformation.submitAllCategories()||!0,EVAL_COOKIEINFORMATION_2:()=>document.cookie.includes("CookieInformationConsent="),EVAL_COOKIEYES_0:()=>document.cookie.includes("advertisement:no"),EVAL_DAILYMOTION_0:()=>!!document.cookie.match("dm-euconsent-v2"),EVAL_DNDBEYOND_TEST:()=>document.cookie.includes("cookie-consent=denied"),EVAL_DSGVO_0:()=>!document.cookie.includes("sp_dsgvo_cookie_settings"),EVAL_DUNELM_0:()=>document.cookie.includes("cc_functional=0")&&document.cookie.includes("cc_targeting=0"),EVAL_ETSY_0:()=>document.querySelectorAll(".gdpr-overlay-body input").forEach((e=>{e.checked=!1}))||!0,EVAL_ETSY_1:()=>document.querySelector(".gdpr-overlay-view button[data-wt-overlay-close]").click()||!0,EVAL_EU_COOKIE_COMPLIANCE_0:()=>-1===document.cookie.indexOf("cookie-agreed=2"),EVAL_EU_COOKIE_LAW_0:()=>!document.cookie.includes("euCookie"),EVAL_EZOIC_0:()=>ezCMP.handleAcceptAllClick(),EVAL_EZOIC_1:()=>!!document.cookie.match(/ez-consent-tcf/),EVAL_FIDES_DETECT_POPUP:()=>window.Fides?.initialized,EVAL_GOOGLE_0:()=>!!document.cookie.match(/SOCS=CAE/),EVAL_HEMA_TEST_0:()=>document.cookie.includes("cookies_rejected=1"),EVAL_IUBENDA_0:()=>document.querySelectorAll(".purposes-item input[type=checkbox]:not([disabled])").forEach((e=>{e.checked&&e.click()}))||!0,EVAL_IUBENDA_1:()=>!!document.cookie.match(/_iub_cs-\d+=/),EVAL_IWINK_TEST:()=>document.cookie.includes("cookie_permission_granted=no"),EVAL_JQUERY_COOKIEBAR_0:()=>!document.cookie.includes("cookies-state=accepted"),EVAL_KETCH_TEST:()=>document.cookie.includes("_ketch_consent_v1_"),EVAL_MEDIAVINE_0:()=>document.querySelectorAll('[data-name="mediavine-gdpr-cmp"] input[type=checkbox]').forEach((e=>e.checked&&e.click()))||!0,EVAL_MICROSOFT_0:()=>Array.from(document.querySelectorAll("div > button")).filter((e=>e.innerText.match("Reject|Ablehnen")))[0].click()||!0,EVAL_MICROSOFT_1:()=>Array.from(document.querySelectorAll("div > button")).filter((e=>e.innerText.match("Accept|Annehmen")))[0].click()||!0,EVAL_MICROSOFT_2:()=>!!document.cookie.match("MSCC|GHCC"),EVAL_MOOVE_0:()=>document.querySelectorAll("#moove_gdpr_cookie_modal input").forEach((e=>{e.disabled||(e.checked="moove_gdpr_strict_cookies"===e.name||"moove_gdpr_strict_cookies"===e.id)}))||!0,EVAL_ONENINETWO_0:()=>document.cookie.includes("CC_ADVERTISING=NO")&&document.cookie.includes("CC_ANALYTICS=NO"),EVAL_OPERA_0:()=>document.cookie.includes("cookie_consent_essential=true")&&!document.cookie.includes("cookie_consent_marketing=true"),EVAL_PAYPAL_0:()=>!0===document.cookie.includes("cookie_prefs"),EVAL_PRIMEBOX_0:()=>!document.cookie.includes("cb-enabled=accepted"),EVAL_PUBTECH_0:()=>document.cookie.includes("euconsent-v2")&&(document.cookie.match(/.YAAAAAAAAAAA/)||document.cookie.match(/.aAAAAAAAAAAA/)||document.cookie.match(/.YAAACFgAAAAA/)),EVAL_REDDIT_0:()=>document.cookie.includes("eu_cookie={%22opted%22:true%2C%22nonessential%22:false}"),EVAL_ROBLOX_TEST:()=>document.cookie.includes("RBXcb"),EVAL_SIRDATA_UNBLOCK_SCROLL:()=>(document.documentElement.classList.forEach((e=>{e.startsWith("sd-cmp-")&&document.documentElement.classList.remove(e)})),!0),EVAL_SNIGEL_0:()=>!!document.cookie.match("snconsent"),EVAL_STEAMPOWERED_0:()=>2===JSON.parse(decodeURIComponent(document.cookie.split(";").find((e=>e.trim().startsWith("cookieSettings"))).split("=")[1])).preference_state,EVAL_SVT_TEST:()=>document.cookie.includes('cookie-consent-1={"optedIn":true,"functionality":false,"statistics":false}'),EVAL_TAKEALOT_0:()=>document.body.classList.remove("freeze")||(document.body.style="")||!0,EVAL_TARTEAUCITRON_0:()=>tarteaucitron.userInterface.respondAll(!1)||!0,EVAL_TARTEAUCITRON_1:()=>tarteaucitron.userInterface.respondAll(!0)||!0,EVAL_TARTEAUCITRON_2:()=>document.cookie.match(/tarteaucitron=[^;]*/)?.[0].includes("false"),EVAL_TAUNTON_TEST:()=>document.cookie.includes("taunton_user_consent_submitted=true"),EVAL_TEALIUM_0:()=>void 0!==window.utag&&"object"==typeof utag.gdpr,EVAL_TEALIUM_1:()=>utag.gdpr.setConsentValue(!1)||!0,EVAL_TEALIUM_DONOTSELL:()=>utag.gdpr.dns?.setDnsState(!1)||!0,EVAL_TEALIUM_2:()=>utag.gdpr.setConsentValue(!0)||!0,EVAL_TEALIUM_3:()=>1!==utag.gdpr.getConsentState(),EVAL_TEALIUM_DONOTSELL_CHECK:()=>1!==utag.gdpr.dns?.getDnsState(),EVAL_TESTCMP_0:()=>"button_clicked"===window.results.results[0],EVAL_TESTCMP_COSMETIC_0:()=>"banner_hidden"===window.results.results[0],EVAL_THEFREEDICTIONARY_0:()=>cmpUi.showPurposes()||cmpUi.rejectAll()||!0,EVAL_THEFREEDICTIONARY_1:()=>cmpUi.allowAll()||!0,EVAL_THEVERGE_0:()=>document.cookie.includes("_duet_gdpr_acknowledged=1"),EVAL_UBUNTU_COM_0:()=>document.cookie.includes("_cookies_accepted=essential"),EVAL_UK_COOKIE_CONSENT_0:()=>!document.cookie.includes("catAccCookies"),EVAL_USERCENTRICS_API_0:()=>"object"==typeof UC_UI,EVAL_USERCENTRICS_API_1:()=>!!UC_UI.closeCMP(),EVAL_USERCENTRICS_API_2:()=>!!UC_UI.denyAllConsents(),EVAL_USERCENTRICS_API_3:()=>!!UC_UI.acceptAllConsents(),EVAL_USERCENTRICS_API_4:()=>!!UC_UI.closeCMP(),EVAL_USERCENTRICS_API_5:()=>!0===UC_UI.areAllConsentsAccepted(),EVAL_USERCENTRICS_API_6:()=>!1===UC_UI.areAllConsentsAccepted(),EVAL_USERCENTRICS_BUTTON_0:()=>JSON.parse(localStorage.getItem("usercentrics")).consents.every((e=>e.isEssential||!e.consentStatus)),EVAL_WAITROSE_0:()=>Array.from(document.querySelectorAll("label[id$=cookies-deny-label]")).forEach((e=>e.click()))||!0,EVAL_WAITROSE_1:()=>document.cookie.includes("wtr_cookies_advertising=0")&&document.cookie.includes("wtr_cookies_analytics=0"),EVAL_WP_COOKIE_NOTICE_0:()=>document.cookie.includes("wpl_viewed_cookie=no"),EVAL_XE_TEST:()=>document.cookie.includes("xeConsentState={%22performance%22:false%2C%22marketing%22:false%2C%22compliance%22:false}"),EVAL_XING_0:()=>document.cookie.includes("userConsent=%7B%22marketing%22%3Afalse"),EVAL_YOUTUBE_DESKTOP_0:()=>!!document.cookie.match(/SOCS=CAE/),EVAL_YOUTUBE_MOBILE_0:()=>!!document.cookie.match(/SOCS=CAE/)};var l={main:!0,frame:!1,urlPattern:""},p=class{constructor(e){this.runContext=l,this.autoconsent=e}get hasSelfTest(){throw new Error("Not Implemented")}get isIntermediate(){throw new Error("Not Implemented")}get isCosmetic(){throw new Error("Not Implemented")}mainWorldEval(e){const t=r[e];if(!t)return console.warn("Snippet not found",e),Promise.resolve(!1);const o=this.autoconsent.config.logs;if(this.autoconsent.config.isMainWorld){o.evals&&console.log("inline eval:",e,t);let c=!1;try{c=!!t.call(globalThis)}catch(t){o.evals&&console.error("error evaluating rule",e,t)}return Promise.resolve(c)}const c=`(${t.toString()})()`;return o.evals&&console.log("async eval:",e,c),s(c,e).catch((t=>(o.evals&&console.error("error evaluating rule",e,t),!1)))}checkRunContext(){const e={...l,...this.runContext},t=window.top===window;return!(t&&!e.main)&&(!(!t&&!e.frame)&&!(e.urlPattern&&!window.location.href.match(e.urlPattern)))}detectCmp(){throw new Error("Not Implemented")}async detectPopup(){return!1}optOut(){throw new Error("Not Implemented")}optIn(){throw new Error("Not Implemented")}openCmp(){throw new Error("Not Implemented")}async test(){return Promise.resolve(!0)}click(e,t=!1){return this.autoconsent.domActions.click(e,t)}elementExists(e){return this.autoconsent.domActions.elementExists(e)}elementVisible(e,t){return this.autoconsent.domActions.elementVisible(e,t)}waitForElement(e,t){return this.autoconsent.domActions.waitForElement(e,t)}waitForVisible(e,t,o){return this.autoconsent.domActions.waitForVisible(e,t,o)}waitForThenClick(e,t,o){return this.autoconsent.domActions.waitForThenClick(e,t,o)}wait(e){return this.autoconsent.domActions.wait(e)}hide(e,t){return this.autoconsent.domActions.hide(e,t)}prehide(e){return this.autoconsent.domActions.prehide(e)}undoPrehide(){return this.autoconsent.domActions.undoPrehide()}querySingleReplySelector(e,t){return this.autoconsent.domActions.querySingleReplySelector(e,t)}querySelectorChain(e){return this.autoconsent.domActions.querySelectorChain(e)}elementSelector(e){return this.autoconsent.domActions.elementSelector(e)}},d=class extends p{constructor(e,t){super(t),this.rule=e,this.name=e.name,this.runContext=e.runContext||l}get hasSelfTest(){return!!this.rule.test}get isIntermediate(){return!!this.rule.intermediate}get isCosmetic(){return!!this.rule.cosmetic}get prehideSelectors(){return this.rule.prehideSelectors}async detectCmp(){return!!this.rule.detectCmp&&this._runRulesParallel(this.rule.detectCmp)}async detectPopup(){return!!this.rule.detectPopup&&this._runRulesSequentially(this.rule.detectPopup)}async optOut(){const e=this.autoconsent.config.logs;return!!this.rule.optOut&&(e.lifecycle&&console.log("Initiated optOut()",this.rule.optOut),this._runRulesSequentially(this.rule.optOut))}async optIn(){const e=this.autoconsent.config.logs;return!!this.rule.optIn&&(e.lifecycle&&console.log("Initiated optIn()",this.rule.optIn),this._runRulesSequentially(this.rule.optIn))}async openCmp(){return!!this.rule.openCmp&&this._runRulesSequentially(this.rule.openCmp)}async test(){return this.hasSelfTest?this._runRulesSequentially(this.rule.test):super.test()}async evaluateRuleStep(e){const t=[],o=this.autoconsent.config.logs;if(e.exists&&t.push(this.elementExists(e.exists)),e.visible&&t.push(this.elementVisible(e.visible,e.check)),e.eval){const o=this.mainWorldEval(e.eval);t.push(o)}if(e.waitFor&&t.push(this.waitForElement(e.waitFor,e.timeout)),e.waitForVisible&&t.push(this.waitForVisible(e.waitForVisible,e.timeout,e.check)),e.click&&t.push(this.click(e.click,e.all)),e.waitForThenClick&&t.push(this.waitForThenClick(e.waitForThenClick,e.timeout,e.all)),e.wait&&t.push(this.wait(e.wait)),e.hide&&t.push(this.hide(e.hide,e.method)),e.if){if(!e.if.exists&&!e.if.visible)return console.error("invalid conditional rule",e.if),!1;const c=await this.evaluateRuleStep(e.if);o.rulesteps&&console.log("Condition is",c),c?t.push(this._runRulesSequentially(e.then)):e.else?t.push(this._runRulesSequentially(e.else)):t.push(!0)}if(e.any){for(const t of e.any)if(await this.evaluateRuleStep(t))return!0;return!1}if(0===t.length)return o.errors&&console.warn("Unrecognized rule",e),!1;return(await Promise.all(t)).reduce(((e,t)=>e&&t),!0)}async _runRulesParallel(e){const t=e.map((e=>this.evaluateRuleStep(e)));return(await Promise.all(t)).every((e=>!!e))}async _runRulesSequentially(e){const t=this.autoconsent.config.logs;for(const o of e){t.rulesteps&&console.log("Running rule...",o);const e=await this.evaluateRuleStep(o);if(t.rulesteps&&console.log("...rule result",e),!e&&!o.optional)return!1}return!0}};function u(e="autoconsent-css-rules"){const t=`style#${e}`,o=document.querySelector(t);if(o&&o instanceof HTMLStyleElement)return o;{const t=document.head||document.getElementsByTagName("head")[0]||document.documentElement,o=document.createElement("style");return o.id=e,t.appendChild(o),o}}function m(e,t,o="display"){const c=`${t} { ${"opacity"===o?"opacity: 0":"display: none"} !important; z-index: -1 !important; pointer-events: none !important; } `;return e instanceof HTMLStyleElement&&(e.innerText+=c,t.length>0)}async function h(e,t,o){const c=await e();return!c&&t>0?new Promise((c=>{setTimeout((async()=>{c(h(e,t-1,o))}),o)})):Promise.resolve(c)}function k(e){if(!e)return!1;if(null!==e.offsetParent)return!0;{const t=window.getComputedStyle(e);if("fixed"===t.position&&"none"!==t.display)return!0}return!1}function b(e){const t={enabled:!0,autoAction:"optOut",disabledCmps:[],enablePrehide:!0,enableCosmeticRules:!0,detectRetries:20,isMainWorld:!1,prehideTimeout:2e3,logs:{lifecycle:!1,rulesteps:!1,evals:!1,errors:!0,messages:!1}},o=(c=t,globalThis.structuredClone?structuredClone(c):JSON.parse(JSON.stringify(c)));var c;for(const c of Object.keys(t))void 0!==e[c]&&(o[c]=e[c]);return o}var _="#truste-show-consent",g="#truste-consent-track",y=[class extends p{constructor(e){super(e),this.name="TrustArc-top",this.prehideSelectors=[".trustarc-banner-container",`.truste_popframe,.truste_overlay,.truste_box_overlay,${g}`],this.runContext={main:!0,frame:!1},this._shortcutButton=null,this._optInDone=!1}get hasSelfTest(){return!0}get isIntermediate(){return!this._optInDone&&!this._shortcutButton}get isCosmetic(){return!1}async detectCmp(){const e=this.elementExists(`${_},${g}`);return e&&(this._shortcutButton=document.querySelector("#truste-consent-required")),e}async detectPopup(){return this.elementVisible(`#truste-consent-content,#trustarc-banner-overlay,${g}`,"all")}openFrame(){this.click(_)}async optOut(){return this._shortcutButton?(this._shortcutButton.click(),!0):(m(u(),`.truste_popframe, .truste_overlay, .truste_box_overlay, ${g}`),this.click(_),setTimeout((()=>{u().remove()}),1e4),!0)}async optIn(){return this._optInDone=!0,this.click("#truste-consent-button")}async openCmp(){return!0}async test(){return await this.wait(500),await this.mainWorldEval("EVAL_TRUSTARC_TOP")}},class extends p{constructor(){super(...arguments),this.name="TrustArc-frame",this.runContext={main:!1,frame:!0,urlPattern:"^https://consent-pref\\.trustarc\\.com/\\?"}}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return!0}async detectPopup(){return this.elementVisible("#defaultpreferencemanager","any")&&this.elementVisible(".mainContent","any")}async navigateToSettings(){return await h((async()=>this.elementExists(".shp")||this.elementVisible(".advance","any")||this.elementExists(".switch span:first-child")),10,500),this.elementExists(".shp")&&this.click(".shp"),await this.waitForElement(".prefPanel",5e3),this.elementVisible(".advance","any")&&this.click(".advance"),await h((()=>this.elementVisible(".switch span:first-child","any")),5,1e3)}async optOut(){if(await this.mainWorldEval("EVAL_TRUSTARC_FRAME_TEST"))return!0;let e=3e3;return await this.mainWorldEval("EVAL_TRUSTARC_FRAME_GTM")&&(e=1500),await h((()=>"complete"===document.readyState),20,100),await this.waitForElement(".mainContent[aria-hidden=false]",e),!!this.click(".rejectAll")||(this.elementExists(".prefPanel")&&await this.waitForElement('.prefPanel[style="visibility: visible;"]',e),this.click("#catDetails0")?(this.click(".submit"),this.waitForThenClick("#gwt-debug-close_id",e),!0):this.click(".required")?(this.waitForThenClick("#gwt-debug-close_id",e),!0):(await this.navigateToSettings(),this.click(".switch span:nth-child(1):not(.active)",!0),this.click(".submit"),this.waitForThenClick("#gwt-debug-close_id",10*e),!0))}async optIn(){return this.click(".call")||(await this.navigateToSettings(),this.click(".switch span:nth-child(2)",!0),this.click(".submit"),this.waitForElement("#gwt-debug-close_id",3e5).then((()=>{this.click("#gwt-debug-close_id")}))),!0}async test(){return await this.wait(500),await this.mainWorldEval("EVAL_TRUSTARC_FRAME_TEST")}},class extends p{constructor(){super(...arguments),this.name="Cybotcookiebot",this.prehideSelectors=["#CybotCookiebotDialog,#CybotCookiebotDialogBodyUnderlay,#dtcookie-container,#cookiebanner,#cb-cookieoverlay,.modal--cookie-banner,#cookiebanner_outer,#CookieBanner"]}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return await this.mainWorldEval("EVAL_COOKIEBOT_1")}async detectPopup(){return this.mainWorldEval("EVAL_COOKIEBOT_2")}async optOut(){await this.wait(500);let e=await this.mainWorldEval("EVAL_COOKIEBOT_3");return await this.wait(500),e=e&&await this.mainWorldEval("EVAL_COOKIEBOT_4"),e}async optIn(){return this.elementExists("#dtcookie-container")?this.click(".h-dtcookie-accept"):(this.click(".CybotCookiebotDialogBodyLevelButton:not(:checked):enabled",!0),this.click("#CybotCookiebotDialogBodyLevelButtonAccept"),this.click("#CybotCookiebotDialogBodyButtonAccept"),!0)}async test(){return await this.wait(500),await this.mainWorldEval("EVAL_COOKIEBOT_5")}},class extends p{constructor(){super(...arguments),this.name="Sourcepoint-frame",this.prehideSelectors=["div[id^='sp_message_container_'],.message-overlay","#sp_privacy_manager_container"],this.ccpaNotice=!1,this.ccpaPopup=!1,this.runContext={main:!0,frame:!0}}get hasSelfTest(){return!1}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){const e=new URL(location.href);return e.searchParams.has("message_id")&&"ccpa-notice.sp-prod.net"===e.hostname?(this.ccpaNotice=!0,!0):"ccpa-pm.sp-prod.net"===e.hostname?(this.ccpaPopup=!0,!0):("/index.html"===e.pathname||"/privacy-manager/index.html"===e.pathname||"/ccpa_pm/index.html"===e.pathname)&&(e.searchParams.has("message_id")||e.searchParams.has("requestUUID")||e.searchParams.has("consentUUID"))}async detectPopup(){return!!this.ccpaNotice||(this.ccpaPopup?await this.waitForElement(".priv-save-btn",2e3):(await this.waitForElement(".sp_choice_type_11,.sp_choice_type_12,.sp_choice_type_13,.sp_choice_type_ACCEPT_ALL,.sp_choice_type_SAVE_AND_EXIT",2e3),!this.elementExists(".sp_choice_type_9")))}async optIn(){return await this.waitForElement(".sp_choice_type_11,.sp_choice_type_ACCEPT_ALL",2e3),!!this.click(".sp_choice_type_11")||!!this.click(".sp_choice_type_ACCEPT_ALL")}isManagerOpen(){return"/privacy-manager/index.html"===location.pathname||"/ccpa_pm/index.html"===location.pathname}async optOut(){const e=this.autoconsent.config.logs;if(this.ccpaPopup){const e=document.querySelectorAll(".priv-purpose-container .sp-switch-arrow-block a.neutral.on .right");for(const t of e)t.click();const t=document.querySelectorAll(".priv-purpose-container .sp-switch-arrow-block a.switch-bg.on");for(const e of t)e.click();return this.click(".priv-save-btn")}if(!this.isManagerOpen()){if(!await this.waitForElement(".sp_choice_type_12,.sp_choice_type_13"))return!1;if(!this.elementExists(".sp_choice_type_12"))return this.click(".sp_choice_type_13");this.click(".sp_choice_type_12"),await h((()=>this.isManagerOpen()),200,100)}await this.waitForElement(".type-modal",2e4),this.waitForThenClick(".ccpa-stack .pm-switch[aria-checked=true] .slider",500,!0);try{const e=".sp_choice_type_REJECT_ALL",t=".reject-toggle",o=await Promise.race([this.waitForElement(e,2e3).then((e=>e?0:-1)),this.waitForElement(t,2e3).then((e=>e?1:-1)),this.waitForElement(".pm-features",2e3).then((e=>e?2:-1))]);if(0===o)return await this.wait(1500),this.click(e);1===o?this.click(t):2===o&&(await this.waitForElement(".pm-features",1e4),this.click(".checked > span",!0),this.click(".chevron"))}catch(t){e.errors&&console.warn(t)}return this.click(".sp_choice_type_SAVE_AND_EXIT")}},class extends p{constructor(){super(...arguments),this.name="consentmanager.net",this.prehideSelectors=["#cmpbox,#cmpbox2"],this.apiAvailable=!1}get hasSelfTest(){return this.apiAvailable}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.apiAvailable=await this.mainWorldEval("EVAL_CONSENTMANAGER_1"),!!this.apiAvailable||this.elementExists("#cmpbox")}async detectPopup(){return this.apiAvailable?(await this.wait(500),await this.mainWorldEval("EVAL_CONSENTMANAGER_2")):this.elementVisible("#cmpbox .cmpmore","any")}async optOut(){return await this.wait(500),this.apiAvailable?await this.mainWorldEval("EVAL_CONSENTMANAGER_3"):!!this.click(".cmpboxbtnno")||(this.elementExists(".cmpwelcomeprpsbtn")?(this.click(".cmpwelcomeprpsbtn > a[aria-checked=true]",!0),this.click(".cmpboxbtnsave"),!0):(this.click(".cmpboxbtncustom"),await this.waitForElement(".cmptblbox",2e3),this.click(".cmptdchoice > a[aria-checked=true]",!0),this.click(".cmpboxbtnyescustomchoices"),this.hide("#cmpwrapper,#cmpbox","display"),!0))}async optIn(){return this.apiAvailable?await this.mainWorldEval("EVAL_CONSENTMANAGER_4"):this.click(".cmpboxbtnyes")}async test(){if(this.apiAvailable)return await this.mainWorldEval("EVAL_CONSENTMANAGER_5")}},class extends p{constructor(){super(...arguments),this.name="Evidon"}get hasSelfTest(){return!1}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists("#_evidon_banner")}async detectPopup(){return this.elementVisible("#_evidon_banner","any")}async optOut(){return this.click("#_evidon-decline-button")||(m(u(),"#evidon-prefdiag-overlay,#evidon-prefdiag-background,#_evidon-background"),await this.waitForThenClick("#_evidon-option-button"),await this.waitForElement("#evidon-prefdiag-overlay",5e3),await this.wait(500),await this.waitForThenClick("#evidon-prefdiag-decline")),!0}async optIn(){return this.click("#_evidon-accept-button")}},class extends p{constructor(){super(...arguments),this.name="Onetrust",this.prehideSelectors=["#onetrust-banner-sdk,#onetrust-consent-sdk,.onetrust-pc-dark-filter,.js-consent-banner"],this.runContext={urlPattern:"^(?!.*https://www\\.nba\\.com/)"}}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists("#onetrust-banner-sdk,#onetrust-pc-sdk")}async detectPopup(){return this.elementVisible("#onetrust-banner-sdk,#onetrust-pc-sdk","any")}async optOut(){return this.elementVisible("#onetrust-reject-all-handler,.ot-pc-refuse-all-handler,.js-reject-cookies","any")?this.click("#onetrust-reject-all-handler,.ot-pc-refuse-all-handler,.js-reject-cookies"):(this.elementExists("#onetrust-pc-btn-handler")?this.click("#onetrust-pc-btn-handler"):this.click(".ot-sdk-show-settings,button.js-cookie-settings"),await this.waitForElement("#onetrust-consent-sdk",2e3),await this.wait(1e3),this.click("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked",!0),await this.wait(1e3),await this.waitForElement(".save-preference-btn-handler,.js-consent-save",2e3),this.click(".save-preference-btn-handler,.js-consent-save"),await this.waitForVisible("#onetrust-banner-sdk",5e3,"none"),!0)}async optIn(){return this.click("#onetrust-accept-btn-handler,#accept-recommended-btn-handler,.js-accept-cookies")}async test(){return await h((()=>this.mainWorldEval("EVAL_ONETRUST_1")),10,500)}},class extends p{constructor(){super(...arguments),this.name="Klaro",this.prehideSelectors=[".klaro"],this.settingsOpen=!1}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists(".klaro > .cookie-modal")?(this.settingsOpen=!0,!0):this.elementExists(".klaro > .cookie-notice")}async detectPopup(){return this.elementVisible(".klaro > .cookie-notice,.klaro > .cookie-modal","any")}async optOut(){return!!await this.mainWorldEval("EVAL_KLARO_TRY_API_OPT_OUT")||(!!this.click(".klaro .cn-decline")||(await this.mainWorldEval("EVAL_KLARO_OPEN_POPUP"),!!this.click(".klaro .cn-decline")||(this.click(".cm-purpose:not(.cm-toggle-all) > input:not(.half-checked,.required,.only-required),.cm-purpose:not(.cm-toggle-all) > div > input:not(.half-checked,.required,.only-required)",!0),this.click(".cm-btn-accept,.cm-button"))))}async optIn(){return!!this.click(".klaro .cm-btn-accept-all")||(this.settingsOpen?(this.click(".cm-purpose:not(.cm-toggle-all) > input.half-checked",!0),this.click(".cm-btn-accept")):this.click(".klaro .cookie-notice .cm-btn-success"))}async test(){return await this.mainWorldEval("EVAL_KLARO_1")}},class extends p{constructor(){super(...arguments),this.name="Uniconsent"}get prehideSelectors(){return[".unic",".modal:has(.unic)"]}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists(".unic .unic-box,.unic .unic-bar,.unic .unic-modal")}async detectPopup(){return this.elementVisible(".unic .unic-box,.unic .unic-bar,.unic .unic-modal","any")}async optOut(){if(await this.waitForElement(".unic button",1e3),document.querySelectorAll(".unic button").forEach((e=>{const t=e.textContent;(t.includes("Manage Options")||t.includes("Optionen verwalten"))&&e.click()})),await this.waitForElement(".unic input[type=checkbox]",1e3)){await this.waitForElement(".unic button",1e3),document.querySelectorAll(".unic input[type=checkbox]").forEach((e=>{e.checked&&e.click()}));for(const e of document.querySelectorAll(".unic button")){const t=e.textContent;for(const o of["Confirm Choices","Save Choices","Auswahl speichern"])if(t.includes(o))return e.click(),await this.wait(500),!0}}return!1}async optIn(){return this.waitForThenClick(".unic #unic-agree")}async test(){await this.wait(1e3);return!this.elementExists(".unic .unic-box,.unic .unic-bar")}},class extends p{constructor(){super(...arguments),this.prehideSelectors=[".cmp-root"],this.name="Conversant"}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists(".cmp-root .cmp-receptacle")}async detectPopup(){return this.elementVisible(".cmp-root .cmp-receptacle","any")}async optOut(){if(!await this.waitForThenClick(".cmp-main-button:not(.cmp-main-button--primary)"))return!1;if(!await this.waitForElement(".cmp-view-tab-tabs"))return!1;await this.waitForThenClick(".cmp-view-tab-tabs > :first-child"),await this.waitForThenClick(".cmp-view-tab-tabs > .cmp-view-tab--active:first-child");for(const e of Array.from(document.querySelectorAll(".cmp-accordion-item"))){e.querySelector(".cmp-accordion-item-title").click(),await h((()=>!!e.querySelector(".cmp-accordion-item-content.cmp-active")),10,50);const t=e.querySelector(".cmp-accordion-item-content.cmp-active");t.querySelectorAll(".cmp-toggle-actions .cmp-toggle-deny:not(.cmp-toggle-deny--active)").forEach((e=>e.click())),t.querySelectorAll(".cmp-toggle-actions .cmp-toggle-checkbox:not(.cmp-toggle-checkbox--active)").forEach((e=>e.click()))}return await this.click(".cmp-main-button:not(.cmp-main-button--primary)"),!0}async optIn(){return this.waitForThenClick(".cmp-main-button.cmp-main-button--primary")}async test(){return document.cookie.includes("cmp-data=0")}},class extends p{constructor(){super(...arguments),this.name="tiktok.com",this.runContext={urlPattern:"tiktok"}}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}getShadowRoot(){const e=document.querySelector("tiktok-cookie-banner");return e?e.shadowRoot:null}async detectCmp(){return this.elementExists("tiktok-cookie-banner")}async detectPopup(){return k(this.getShadowRoot().querySelector(".tiktok-cookie-banner"))}async optOut(){const e=this.autoconsent.config.logs,t=this.getShadowRoot().querySelector(".button-wrapper button:first-child");return t?(e.rulesteps&&console.log("[clicking]",t),t.click(),!0):(e.errors&&console.log("no decline button found"),!1)}async optIn(){const e=this.autoconsent.config.logs,t=this.getShadowRoot().querySelector(".button-wrapper button:last-child");return t?(e.rulesteps&&console.log("[clicking]",t),t.click(),!0):(e.errors&&console.log("no accept button found"),!1)}async test(){const e=document.cookie.match(/cookie-consent=([^;]+)/);if(!e)return!1;const t=JSON.parse(decodeURIComponent(e[1]));return Object.values(t).every((e=>"boolean"!=typeof e||!1===e))}},class extends p{constructor(){super(...arguments),this.runContext={urlPattern:"^https://(www\\.)?airbnb\\.[^/]+/"},this.prehideSelectors=["div[data-testid=main-cookies-banner-container]",'div:has(> div:first-child):has(> div:last-child):has(> section [data-testid="strictly-necessary-cookies"])']}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists("div[data-testid=main-cookies-banner-container]")}async detectPopup(){return this.elementVisible("div[data-testid=main-cookies-banner-container","any")}async optOut(){let e;for(await this.waitForThenClick("div[data-testid=main-cookies-banner-container] button._snbhip0");e=document.querySelector("[data-testid=modal-container] button[aria-checked=true]:not([disabled])");)e.click();return this.waitForThenClick("button[data-testid=save-btn]")}async optIn(){return this.waitForThenClick("div[data-testid=main-cookies-banner-container] button._148dgdpk")}async test(){return await h((()=>!!document.cookie.match("OptanonAlertBoxClosed")),20,200)}},class extends p{constructor(){super(...arguments),this.name="tumblr-com",this.runContext={urlPattern:"^https://(www\\.)?tumblr\\.com/"}}get hasSelfTest(){return!1}get isIntermediate(){return!1}get isCosmetic(){return!1}get prehideSelectors(){return["#cmp-app-container"]}async detectCmp(){return this.elementExists("#cmp-app-container")}async detectPopup(){return this.elementVisible("#cmp-app-container","any")}async optOut(){let e=document.querySelector("#cmp-app-container iframe"),t=e.contentDocument?.querySelector(".cmp-components-button.is-secondary");return!!t&&(t.click(),await h((()=>!!document.querySelector("#cmp-app-container iframe").contentDocument?.querySelector(".cmp__dialog input")),5,500),e=document.querySelector("#cmp-app-container iframe"),t=e.contentDocument?.querySelector(".cmp-components-button.is-secondary"),!!t&&(t.click(),!0))}async optIn(){const e=document.querySelector("#cmp-app-container iframe").contentDocument.querySelector(".cmp-components-button.is-primary");return!!e&&(e.click(),!0)}}];var w=[{name:"192.com",detectCmp:[{exists:".ont-cookies"}],detectPopup:[{visible:".ont-cookies"}],optIn:[{click:".ont-btn-main.ont-cookies-btn.js-ont-btn-ok2"}],optOut:[{click:".ont-cookes-btn-manage"},{click:".ont-btn-main.ont-cookies-btn.js-ont-btn-choose"}],test:[{eval:"EVAL_ONENINETWO_0"}]},{name:"1password-com",cosmetic:!0,prehideSelectors:['footer #footer-root [aria-label="Cookie Consent"]'],detectCmp:[{exists:'footer #footer-root [aria-label="Cookie Consent"]'}],detectPopup:[{visible:'footer #footer-root [aria-label="Cookie Consent"]'}],optIn:[{click:'footer #footer-root [aria-label="Cookie Consent"] button'}],optOut:[{hide:'footer #footer-root [aria-label="Cookie Consent"]'}]},{name:"abconcerts.be",vendorUrl:"https://unknown",intermediate:!1,prehideSelectors:["dialog.cookie-consent"],detectCmp:[{exists:"dialog.cookie-consent form.cookie-consent__form"}],detectPopup:[{visible:"dialog.cookie-consent form.cookie-consent__form"}],optIn:[{waitForThenClick:"dialog.cookie-consent form.cookie-consent__form button[value=yes]"}],optOut:[{if:{exists:"dialog.cookie-consent form.cookie-consent__form button[value=no]"},then:[{click:"dialog.cookie-consent form.cookie-consent__form button[value=no]"}],else:[{click:"dialog.cookie-consent form.cookie-consent__form button.cookie-consent__options-toggle"},{waitForThenClick:'dialog.cookie-consent form.cookie-consent__form button[value="save_options"]'}]}]},{name:"activobank.pt",runContext:{urlPattern:"^https://(www\\.)?activobank\\.pt"},prehideSelectors:["aside#cookies,.overlay-cookies"],detectCmp:[{exists:"#cookies .cookies-btn"}],detectPopup:[{visible:"#cookies #submitCookies"}],optIn:[{waitForThenClick:"#cookies #submitCookies"}],optOut:[{waitForThenClick:"#cookies #rejectCookies"}]},{name:"Adroll",prehideSelectors:["#adroll_consent_container"],detectCmp:[{exists:"#adroll_consent_container"}],detectPopup:[{visible:"#adroll_consent_container"}],optIn:[{waitForThenClick:"#adroll_consent_accept"}],optOut:[{waitForThenClick:"#adroll_consent_reject"}],test:[{eval:"EVAL_ADROLL_0"}]},{name:"affinity.serif.com",detectCmp:[{exists:".c-cookie-banner button[data-qa='allow-all-cookies']"}],detectPopup:[{visible:".c-cookie-banner"}],optIn:[{click:'button[data-qa="allow-all-cookies"]'}],optOut:[{click:'button[data-qa="manage-cookies"]'},{waitFor:'.c-cookie-banner ~ [role="dialog"]'},{waitForThenClick:'.c-cookie-banner ~ [role="dialog"] input[type="checkbox"][value="true"]',all:!0},{click:'.c-cookie-banner ~ [role="dialog"] .c-modal__action button'}],test:[{wait:500},{eval:"EVAL_AFFINITY_SERIF_COM_0"}]},{name:"agolde.com",cosmetic:!0,prehideSelectors:["#modal-1 div[data-micromodal-close]"],detectCmp:[{exists:"#modal-1 div[aria-labelledby=modal-1-title]"}],detectPopup:[{exists:"#modal-1 div[data-micromodal-close]"}],optIn:[{click:'button[aria-label="Close modal"]'}],optOut:[{hide:"#modal-1 div[data-micromodal-close]"}]},{name:"aliexpress",vendorUrl:"https://aliexpress.com/",runContext:{urlPattern:"^https://.*\\.aliexpress\\.com/"},prehideSelectors:["#gdpr-new-container"],detectCmp:[{exists:"#gdpr-new-container"}],detectPopup:[{visible:"#gdpr-new-container"}],optIn:[{waitForThenClick:"#gdpr-new-container .btn-accept"}],optOut:[{waitForThenClick:"#gdpr-new-container .btn-more"},{waitFor:"#gdpr-new-container .gdpr-dialog-switcher"},{click:"#gdpr-new-container .switcher-on",all:!0,optional:!0},{click:"#gdpr-new-container .btn-save"}]},{name:"almacmp",prehideSelectors:["#alma-cmpv2-container"],detectCmp:[{exists:"#alma-cmpv2-container"}],detectPopup:[{visible:"#alma-cmpv2-container #almacmp-modal-layer1"}],optIn:[{waitForThenClick:"#alma-cmpv2-container #almacmp-modal-layer1 #almacmp-modalConfirmBtn"}],optOut:[{waitForThenClick:"#alma-cmpv2-container #almacmp-modal-layer1 #almacmp-modalSettingBtn"},{waitFor:"#alma-cmpv2-container #almacmp-modal-layer2"},{waitForThenClick:"#alma-cmpv2-container #almacmp-modal-layer2 #almacmp-reject-all-layer2"}],test:[{eval:"EVAL_ALMACMP_0"}]},{name:"altium.com",cosmetic:!0,prehideSelectors:[".altium-privacy-bar"],detectCmp:[{exists:".altium-privacy-bar"}],detectPopup:[{exists:".altium-privacy-bar"}],optIn:[{click:"a.altium-privacy-bar__btn"}],optOut:[{hide:".altium-privacy-bar"}]},{name:"amazon.com",prehideSelectors:['span[data-action="sp-cc"][data-sp-cc*="rejectAllAction"]'],detectCmp:[{exists:'span[data-action="sp-cc"][data-sp-cc*="rejectAllAction"]'}],detectPopup:[{visible:'span[data-action="sp-cc"][data-sp-cc*="rejectAllAction"]'}],optIn:[{waitForVisible:"#sp-cc-accept"},{wait:500},{click:"#sp-cc-accept"}],optOut:[{waitForVisible:"#sp-cc-rejectall-link"},{wait:500},{click:"#sp-cc-rejectall-link"}]},{name:"aquasana.com",prehideSelectors:["#consent-tracking"],detectCmp:[{exists:"#consent-tracking"}],detectPopup:[{exists:"#consent-tracking"}],optIn:[{waitForThenClick:"#consent-tracking .affirm.btn"}],optOut:[{if:{exists:"#consent-tracking .decline.btn"},then:[{click:"#consent-tracking .decline.btn"}],else:[{hide:"#consent-tracking"}]}]},{name:"arbeitsagentur",vendorUrl:"https://www.arbeitsagentur.de/",prehideSelectors:[".modal-open bahf-cookie-disclaimer-dpl3"],detectCmp:[{exists:"bahf-cookie-disclaimer-dpl3"}],detectPopup:[{visible:"bahf-cookie-disclaimer-dpl3"}],optIn:[{waitForThenClick:["bahf-cookie-disclaimer-dpl3","bahf-cd-modal-dpl3 .ba-btn-primary"]}],optOut:[{waitForThenClick:["bahf-cookie-disclaimer-dpl3","bahf-cd-modal-dpl3 .ba-btn-contrast"]}],test:[{eval:"EVAL_ARBEITSAGENTUR_TEST"}]},{name:"asus",vendorUrl:"https://www.asus.com/",runContext:{urlPattern:"^https://www\\.asus\\.com/"},prehideSelectors:["#cookie-policy-info,#cookie-policy-info-bg"],detectCmp:[{exists:"#cookie-policy-info"}],detectPopup:[{visible:"#cookie-policy-info"}],optIn:[{waitForThenClick:'#cookie-policy-info [data-agree="Accept Cookies"]'}],optOut:[{if:{exists:"#cookie-policy-info .btn-reject"},then:[{waitForThenClick:"#cookie-policy-info .btn-reject"}],else:[{waitForThenClick:"#cookie-policy-info .btn-setting"},{waitForThenClick:'#cookie-policy-lightbox-wrapper [data-agree="Save Settings"]'}]}]},{name:"athlinks-com",runContext:{urlPattern:"^https://(www\\.)?athlinks\\.com/"},cosmetic:!0,prehideSelectors:["#footer-container ~ div"],detectCmp:[{exists:"#footer-container ~ div"}],detectPopup:[{visible:"#footer-container > div"}],optIn:[{click:"#footer-container ~ div button"}],optOut:[{hide:"#footer-container ~ div"}]},{name:"ausopen.com",cosmetic:!0,detectCmp:[{exists:".gdpr-popup__message"}],detectPopup:[{visible:".gdpr-popup__message"}],optOut:[{hide:".gdpr-popup__message"}],optIn:[{click:".gdpr-popup__message button"}]},{name:"automattic-cmp-optout",prehideSelectors:['form[class*="cookie-banner"][method="post"]'],detectCmp:[{exists:'form[class*="cookie-banner"][method="post"]'}],detectPopup:[{visible:'form[class*="cookie-banner"][method="post"]'}],optIn:[{click:'a[class*="accept-all-button"]'}],optOut:[{click:'form[class*="cookie-banner"] div[class*="simple-options"] a[class*="customize-button"]'},{waitForThenClick:"input[type=checkbox][checked]:not([disabled])",all:!0},{click:'a[class*="accept-selection-button"]'}]},{name:"aws.amazon.com",prehideSelectors:["#awsccc-cb-content","#awsccc-cs-container","#awsccc-cs-modalOverlay","#awsccc-cs-container-inner"],detectCmp:[{exists:"#awsccc-cb-content"}],detectPopup:[{visible:"#awsccc-cb-content"}],optIn:[{click:"button[data-id=awsccc-cb-btn-accept"}],optOut:[{click:"button[data-id=awsccc-cb-btn-customize]"},{waitFor:"input[aria-checked]"},{click:"input[aria-checked=true]",all:!0,optional:!0},{click:"button[data-id=awsccc-cs-btn-save]"}]},{name:"axeptio",prehideSelectors:[".axeptio_widget"],detectCmp:[{exists:".axeptio_widget"}],detectPopup:[{visible:".axeptio_widget"}],optIn:[{waitFor:".axeptio-widget--open"},{click:"button#axeptio_btn_acceptAll"}],optOut:[{waitFor:".axeptio-widget--open"},{click:"button#axeptio_btn_dismiss"}],test:[{eval:"EVAL_AXEPTIO_0"}]},{name:"baden-wuerttemberg.de",prehideSelectors:[".cookie-alert.t-dark"],cosmetic:!0,detectCmp:[{exists:".cookie-alert.t-dark"}],detectPopup:[{visible:".cookie-alert.t-dark"}],optIn:[{click:".cookie-alert__form input:not([disabled]):not([checked])"},{click:".cookie-alert__button button"}],optOut:[{hide:".cookie-alert.t-dark"}]},{name:"bahn-de",vendorUrl:"https://www.bahn.de/",cosmetic:!1,runContext:{main:!0,frame:!1,urlPattern:"^https://(www\\.)?bahn\\.de/"},intermediate:!1,prehideSelectors:[],detectCmp:[{exists:["body > div:first-child","#consent-layer"]}],detectPopup:[{visible:["body > div:first-child","#consent-layer"]}],optIn:[{waitForThenClick:["body > div:first-child","#consent-layer .js-accept-all-cookies"]}],optOut:[{waitForThenClick:["body > div:first-child","#consent-layer .js-accept-essential-cookies"]}],test:[{eval:"EVAL_BAHN_TEST"}]},{name:"bbb.org",runContext:{urlPattern:"^https://www\\.bbb\\.org/"},cosmetic:!0,prehideSelectors:['div[aria-label="use of cookies on bbb.org"]'],detectCmp:[{exists:'div[aria-label="use of cookies on bbb.org"]'}],detectPopup:[{visible:'div[aria-label="use of cookies on bbb.org"]'}],optIn:[{click:'div[aria-label="use of cookies on bbb.org"] button.bds-button-unstyled span.visually-hidden'}],optOut:[{hide:'div[aria-label="use of cookies on bbb.org"]'}]},{name:"bing.com",prehideSelectors:["#bnp_container"],detectCmp:[{exists:"#bnp_cookie_banner"}],detectPopup:[{visible:"#bnp_cookie_banner"}],optIn:[{click:"#bnp_btn_accept"}],optOut:[{click:"#bnp_btn_preference"},{click:"#mcp_savesettings"}],test:[{eval:"EVAL_BING_0"}]},{name:"blocksy",vendorUrl:"https://creativethemes.com/blocksy/docs/extensions/cookies-consent/",cosmetic:!1,runContext:{main:!0,frame:!1},intermediate:!1,prehideSelectors:[".cookie-notification"],detectCmp:[{exists:"#blocksy-ext-cookies-consent-styles-css"}],detectPopup:[{visible:".cookie-notification"}],optIn:[{click:".cookie-notification .ct-cookies-decline-button"}],optOut:[{waitForThenClick:".cookie-notification .ct-cookies-decline-button"}],test:[{eval:"EVAL_BLOCKSY_0"}]},{name:"borlabs",detectCmp:[{exists:"._brlbs-block-content"}],detectPopup:[{visible:"._brlbs-bar-wrap,._brlbs-box-wrap"}],optIn:[{click:"a[data-cookie-accept-all]"}],optOut:[{click:"a[data-cookie-individual]"},{waitForVisible:".cookie-preference"},{click:"input[data-borlabs-cookie-checkbox]:checked",all:!0,optional:!0},{click:"#CookiePrefSave"},{wait:500}],prehideSelectors:["#BorlabsCookieBox"],test:[{eval:"EVAL_BORLABS_0"}]},{name:"bundesregierung.de",prehideSelectors:[".bpa-cookie-banner"],detectCmp:[{exists:".bpa-cookie-banner"}],detectPopup:[{visible:".bpa-cookie-banner .bpa-module-full-hero"}],optIn:[{click:".bpa-accept-all-button"}],optOut:[{wait:500,comment:"click is not immediately recognized"},{waitForThenClick:".bpa-close-button"}],test:[{eval:"EVAL_BUNDESREGIERUNG_DE_0"}]},{name:"burpee.com",cosmetic:!0,prehideSelectors:["#notice-cookie-block"],detectCmp:[{exists:"#notice-cookie-block"}],detectPopup:[{exists:"#html-body #notice-cookie-block"}],optIn:[{click:"#btn-cookie-allow"}],optOut:[{hide:"#html-body #notice-cookie-block, #notice-cookie"}]},{name:"canva.com",prehideSelectors:['div[role="dialog"] a[data-anchor-id="cookie-policy"]'],detectCmp:[{exists:'div[role="dialog"] a[data-anchor-id="cookie-policy"]'}],detectPopup:[{exists:'div[role="dialog"] a[data-anchor-id="cookie-policy"]'}],optIn:[{click:'div[role="dialog"] button:nth-child(1)'}],optOut:[{if:{exists:'div[role="dialog"] button:nth-child(3)'},then:[{click:'div[role="dialog"] button:nth-child(2)'}],else:[{click:'div[role="dialog"] button:nth-child(2)'},{waitFor:'div[role="dialog"] a[data-anchor-id="cookie-policy"]'},{waitFor:'div[role="dialog"] button[role=switch]'},{click:'div[role="dialog"] button:nth-child(2):not([role])'},{click:'div[role="dialog"] div:last-child button:only-child'}]}],test:[{eval:"EVAL_CANVA_0"}]},{name:"canyon.com",runContext:{urlPattern:"^https://www\\.canyon\\.com/"},prehideSelectors:["div.modal.cookiesModal.is-open"],detectCmp:[{exists:"div.modal.cookiesModal.is-open"}],detectPopup:[{visible:"div.modal.cookiesModal.is-open"}],optIn:[{click:'div.cookiesModal__buttonWrapper > button[data-closecause="close-by-submit"]'}],optOut:[{click:'div.cookiesModal__buttonWrapper > button[data-closecause="close-by-manage-cookies"]'},{waitForThenClick:"button#js-manage-data-privacy-save-button"}]},{name:"cc-banner-springer",prehideSelectors:[".cc-banner[data-cc-banner]"],detectCmp:[{exists:".cc-banner[data-cc-banner]"}],detectPopup:[{visible:".cc-banner[data-cc-banner]"}],optIn:[{waitForThenClick:".cc-banner[data-cc-banner] button[data-cc-action=accept]"}],optOut:[{if:{exists:".cc-banner[data-cc-banner] button[data-cc-action=reject]"},then:[{click:".cc-banner[data-cc-banner] button[data-cc-action=reject]"}],else:[{waitForThenClick:".cc-banner[data-cc-banner] button[data-cc-action=preferences]"},{waitFor:".cc-preferences[data-cc-preferences]"},{click:".cc-preferences[data-cc-preferences] input[type=radio][data-cc-action=toggle-category][value=off]",all:!0,optional:!0},{if:{exists:".cc-preferences[data-cc-preferences] button[data-cc-action=reject]"},then:[{click:".cc-preferences[data-cc-preferences] button[data-cc-action=reject]"}],else:[{click:".cc-preferences[data-cc-preferences] button[data-cc-action=save]"}]}]}],test:[{eval:"EVAL_CC_BANNER2_0"}]},{name:"cc_banner",cosmetic:!0,prehideSelectors:[".cc_banner-wrapper"],detectCmp:[{exists:".cc_banner-wrapper"}],detectPopup:[{visible:".cc_banner"}],optIn:[{click:".cc_btn_accept_all"}],optOut:[{hide:".cc_banner-wrapper"}]},{name:"ciaopeople.it",prehideSelectors:["#cp-gdpr-choices"],detectCmp:[{exists:"#cp-gdpr-choices"}],detectPopup:[{visible:"#cp-gdpr-choices"}],optIn:[{waitForThenClick:".gdpr-btm__right > button:nth-child(2)"}],optOut:[{waitForThenClick:".gdpr-top-content > button"},{waitFor:".gdpr-top-back"},{waitForThenClick:".gdpr-btm__right > button:nth-child(1)"}],test:[{visible:"#cp-gdpr-choices",check:"none"}]},{vendorUrl:"https://www.civicuk.com/cookie-control/",name:"civic-cookie-control",prehideSelectors:["#ccc-module,#ccc-overlay"],detectCmp:[{exists:"#ccc-module"}],detectPopup:[{visible:"#ccc"},{visible:"#ccc-module"}],optOut:[{click:"#ccc-reject-settings"}],optIn:[{click:"#ccc-recommended-settings"}]},{name:"click.io",prehideSelectors:["#cl-consent"],detectCmp:[{exists:"#cl-consent"}],detectPopup:[{visible:"#cl-consent"}],optIn:[{waitForThenClick:'#cl-consent [data-role="b_agree"]'}],optOut:[{waitFor:'#cl-consent [data-role="b_options"]'},{wait:500},{click:'#cl-consent [data-role="b_options"]'},{waitFor:'.cl-consent-popup.cl-consent-visible [data-role="alloff"]'},{click:'.cl-consent-popup.cl-consent-visible [data-role="alloff"]',all:!0},{click:'[data-role="b_save"]'}],test:[{eval:"EVAL_CLICKIO_0",comment:"TODO: this only checks if we interacted at all"}]},{name:"clinch",intermediate:!1,runContext:{frame:!1,main:!0},prehideSelectors:[".consent-modal[role=dialog]"],detectCmp:[{exists:".consent-modal[role=dialog]"}],detectPopup:[{visible:".consent-modal[role=dialog]"}],optIn:[{click:"#consent_agree"}],optOut:[{if:{exists:"#consent_reject"},then:[{click:"#consent_reject"}],else:[{click:"#manage_cookie_preferences"},{click:"#cookie_consent_preferences input:checked",all:!0,optional:!0},{click:"#consent_save"}]}],test:[{eval:"EVAL_CLINCH_0"}]},{name:"clustrmaps.com",runContext:{urlPattern:"^https://(www\\.)?clustrmaps\\.com/"},cosmetic:!0,prehideSelectors:["#gdpr-cookie-message"],detectCmp:[{exists:"#gdpr-cookie-message"}],detectPopup:[{visible:"#gdpr-cookie-message"}],optIn:[{click:"button#gdpr-cookie-accept"}],optOut:[{hide:"#gdpr-cookie-message"}]},{name:"coinbase",intermediate:!1,runContext:{frame:!0,main:!0,urlPattern:"^https://(www|help)\\.coinbase\\.com"},prehideSelectors:[],detectCmp:[{exists:"div[class^=CookieBannerContent__Container]"}],detectPopup:[{visible:"div[class^=CookieBannerContent__Container]"}],optIn:[{click:"div[class^=CookieBannerContent__CTA] :nth-last-child(1)"}],optOut:[{click:"button[class^=CookieBannerContent__Settings]"},{click:"div[class^=CookiePreferencesModal__CategoryContainer] input:checked",all:!0,optional:!0},{click:"div[class^=CookiePreferencesModal__ButtonContainer] > button"}],test:[{eval:"EVAL_COINBASE_0"}]},{name:"Complianz banner",prehideSelectors:["#cmplz-cookiebanner-container"],detectCmp:[{exists:"#cmplz-cookiebanner-container .cmplz-cookiebanner"}],detectPopup:[{visible:"#cmplz-cookiebanner-container .cmplz-cookiebanner",check:"any"}],optIn:[{waitForThenClick:".cmplz-cookiebanner .cmplz-accept"}],optOut:[{waitForThenClick:".cmplz-cookiebanner .cmplz-deny"}],test:[{eval:"EVAL_COMPLIANZ_BANNER_0"}]},{name:"Complianz categories",prehideSelectors:['.cc-type-categories[aria-describedby="cookieconsent:desc"]'],detectCmp:[{exists:'.cc-type-categories[aria-describedby="cookieconsent:desc"]'}],detectPopup:[{visible:'.cc-type-categories[aria-describedby="cookieconsent:desc"]'}],optIn:[{any:[{click:".cc-accept-all"},{click:".cc-allow-all"},{click:".cc-allow"},{click:".cc-dismiss"}]}],optOut:[{if:{exists:'.cc-type-categories[aria-describedby="cookieconsent:desc"] .cc-dismiss'},then:[{click:".cc-dismiss"}],else:[{click:".cc-type-categories input[type=checkbox]:not([disabled]):checked",all:!0,optional:!0},{click:".cc-save"}]}]},{name:"Complianz notice",prehideSelectors:['.cc-type-info[aria-describedby="cookieconsent:desc"]'],cosmetic:!0,detectCmp:[{exists:'.cc-type-info[aria-describedby="cookieconsent:desc"] .cc-compliance .cc-btn'}],detectPopup:[{visible:'.cc-type-info[aria-describedby="cookieconsent:desc"] .cc-compliance .cc-btn'}],optIn:[{click:".cc-accept-all",optional:!0},{click:".cc-allow",optional:!0},{click:".cc-dismiss",optional:!0}],optOut:[{if:{exists:".cc-deny"},then:[{click:".cc-deny"}],else:[{hide:'[aria-describedby="cookieconsent:desc"]'}]}]},{name:"Complianz opt-both",prehideSelectors:['[aria-describedby="cookieconsent:desc"] .cc-type-opt-both'],detectCmp:[{exists:'[aria-describedby="cookieconsent:desc"] .cc-type-opt-both'}],detectPopup:[{visible:'[aria-describedby="cookieconsent:desc"] .cc-type-opt-both'}],optIn:[{click:".cc-accept-all",optional:!0},{click:".cc-allow",optional:!0},{click:".cc-dismiss",optional:!0}],optOut:[{waitForThenClick:".cc-deny"}]},{name:"Complianz opt-out",prehideSelectors:['[aria-describedby="cookieconsent:desc"].cc-type-opt-out'],detectCmp:[{exists:'[aria-describedby="cookieconsent:desc"].cc-type-opt-out'}],detectPopup:[{visible:'[aria-describedby="cookieconsent:desc"].cc-type-opt-out'}],optIn:[{click:".cc-accept-all",optional:!0},{click:".cc-allow",optional:!0},{click:".cc-dismiss",optional:!0}],optOut:[{if:{exists:".cc-deny"},then:[{click:".cc-deny"}],else:[{if:{exists:".cmp-pref-link"},then:[{click:".cmp-pref-link"},{waitForThenClick:".cmp-body [id*=rejectAll]"},{waitForThenClick:".cmp-body .cmp-save-btn"}]}]}]},{name:"Complianz optin",prehideSelectors:['.cc-type-opt-in[aria-describedby="cookieconsent:desc"]'],detectCmp:[{exists:'.cc-type-opt-in[aria-describedby="cookieconsent:desc"]'}],detectPopup:[{visible:'.cc-type-opt-in[aria-describedby="cookieconsent:desc"]'}],optIn:[{any:[{click:".cc-accept-all"},{click:".cc-allow"},{click:".cc-dismiss"}]}],optOut:[{if:{visible:".cc-deny"},then:[{click:".cc-deny"}],else:[{if:{visible:".cc-settings"},then:[{waitForThenClick:".cc-settings"},{waitForVisible:".cc-settings-view"},{click:".cc-settings-view input[type=checkbox]:not([disabled]):checked",all:!0,optional:!0},{click:".cc-settings-view .cc-btn-accept-selected"}],else:[{click:".cc-dismiss"}]}]}]},{name:"cookie-law-info",prehideSelectors:["#cookie-law-info-bar"],detectCmp:[{exists:"#cookie-law-info-bar"},{eval:"EVAL_COOKIE_LAW_INFO_DETECT"}],detectPopup:[{visible:"#cookie-law-info-bar"}],optIn:[{click:'[data-cli_action="accept_all"]'}],optOut:[{hide:"#cookie-law-info-bar"},{eval:"EVAL_COOKIE_LAW_INFO_0"}],test:[{eval:"EVAL_COOKIE_LAW_INFO_1"}]},{name:"cookie-manager-popup",cosmetic:!1,runContext:{main:!0,frame:!1},intermediate:!1,detectCmp:[{exists:"#notice-cookie-block #allow-functional-cookies, #notice-cookie-block #btn-cookie-settings"}],detectPopup:[{visible:"#notice-cookie-block"}],optIn:[{click:"#btn-cookie-allow"}],optOut:[{if:{exists:"#allow-functional-cookies"},then:[{click:"#allow-functional-cookies"}],else:[{waitForThenClick:"#btn-cookie-settings"},{waitForVisible:".modal-body"},{click:'.modal-body input:checked, .switch[data-switch="on"]',all:!0,optional:!0},{click:'[role="dialog"] .modal-footer button'}]}],prehideSelectors:["#btn-cookie-settings"],test:[{eval:"EVAL_COOKIE_MANAGER_POPUP_0"}]},{name:"cookie-notice",prehideSelectors:["#cookie-notice"],cosmetic:!0,detectCmp:[{visible:"#cookie-notice .cookie-notice-container"}],detectPopup:[{visible:"#cookie-notice"}],optIn:[{click:"#cn-accept-cookie"}],optOut:[{hide:"#cookie-notice"}]},{name:"cookie-script",vendorUrl:"https://cookie-script.com/",prehideSelectors:["#cookiescript_injected"],detectCmp:[{exists:"#cookiescript_injected"}],detectPopup:[{visible:"#cookiescript_injected"}],optOut:[{if:{exists:"#cookiescript_reject"},then:[{wait:100},{click:"#cookiescript_reject"}],else:[{click:"#cookiescript_manage"},{waitForVisible:".cookiescript_fsd_main"},{waitForThenClick:"#cookiescript_reject"}]}],optIn:[{click:"#cookiescript_accept"}]},{name:"cookieacceptbar",vendorUrl:"https://unknown",cosmetic:!0,prehideSelectors:["#cookieAcceptBar.cookieAcceptBar"],detectCmp:[{exists:"#cookieAcceptBar.cookieAcceptBar"}],detectPopup:[{visible:"#cookieAcceptBar.cookieAcceptBar"}],optIn:[{waitForThenClick:"#cookieAcceptBarConfirm"}],optOut:[{hide:"#cookieAcceptBar.cookieAcceptBar"}]},{name:"cookiealert",intermediate:!1,prehideSelectors:[],runContext:{frame:!0,main:!0},detectCmp:[{exists:".cookie-alert-extended"}],detectPopup:[{visible:".cookie-alert-extended-modal"}],optIn:[{click:"button[data-controller='cookie-alert/extended/button/accept']"},{eval:"EVAL_COOKIEALERT_0"}],optOut:[{click:"a[data-controller='cookie-alert/extended/detail-link']"},{click:".cookie-alert-configuration-input:checked",all:!0,optional:!0},{click:"button[data-controller='cookie-alert/extended/button/configuration']"},{eval:"EVAL_COOKIEALERT_0"}],test:[{eval:"EVAL_COOKIEALERT_2"}]},{name:"cookieconsent2",vendorUrl:"https://www.github.com/orestbida/cookieconsent",comment:"supports v2.x.x of the library",prehideSelectors:["#cc--main"],detectCmp:[{exists:"#cc--main"}],detectPopup:[{visible:"#cm"},{exists:"#s-all-bn"}],optIn:[{waitForThenClick:"#s-all-bn"}],optOut:[{waitForThenClick:"#s-rall-bn"}],test:[{eval:"EVAL_COOKIECONSENT2_TEST"}]},{name:"cookieconsent3",vendorUrl:"https://www.github.com/orestbida/cookieconsent",comment:"supports v3.x.x of the library",prehideSelectors:["#cc-main"],detectCmp:[{exists:"#cc-main"}],detectPopup:[{visible:"#cc-main .cm-wrapper"}],optIn:[{waitForThenClick:".cm__btn[data-role=all]"}],optOut:[{waitForThenClick:".cm__btn[data-role=necessary]"}],test:[{eval:"EVAL_COOKIECONSENT3_TEST"}]},{name:"cookiecuttr",vendorUrl:"https://github.com/cdwharton/cookieCuttr",cosmetic:!1,runContext:{main:!0,frame:!1,urlPattern:""},prehideSelectors:[".cc-cookies"],detectCmp:[{exists:".cc-cookies .cc-cookie-accept"}],detectPopup:[{visible:".cc-cookies .cc-cookie-accept"}],optIn:[{waitForThenClick:".cc-cookies .cc-cookie-accept"}],optOut:[{if:{exists:".cc-cookies .cc-cookie-decline"},then:[{click:".cc-cookies .cc-cookie-decline"}],else:[{hide:".cc-cookies"}]}]},{name:"cookiefirst.com",prehideSelectors:["#cookiefirst-root,.cookiefirst-root,[aria-labelledby=cookie-preference-panel-title]"],detectCmp:[{exists:"#cookiefirst-root,.cookiefirst-root"}],detectPopup:[{visible:"#cookiefirst-root,.cookiefirst-root"}],optIn:[{click:"button[data-cookiefirst-action=accept]"}],optOut:[{if:{exists:"button[data-cookiefirst-action=adjust]"},then:[{click:"button[data-cookiefirst-action=adjust]"},{waitForVisible:"[data-cookiefirst-widget=modal]",timeout:1e3},{eval:"EVAL_COOKIEFIRST_1"},{wait:1e3},{click:"button[data-cookiefirst-action=save]"}],else:[{click:"button[data-cookiefirst-action=reject]"}]}],test:[{eval:"EVAL_COOKIEFIRST_0"}]},{name:"Cookie Information Banner",prehideSelectors:["#cookie-information-template-wrapper"],detectCmp:[{exists:"#cookie-information-template-wrapper"}],detectPopup:[{visible:"#cookie-information-template-wrapper"}],optIn:[{eval:"EVAL_COOKIEINFORMATION_1"}],optOut:[{hide:"#cookie-information-template-wrapper",comment:"some templates don't hide the banner automatically"},{eval:"EVAL_COOKIEINFORMATION_0"}],test:[{eval:"EVAL_COOKIEINFORMATION_2"}]},{name:"cookieyes",prehideSelectors:[".cky-overlay,.cky-consent-container"],detectCmp:[{exists:".cky-consent-container"}],detectPopup:[{visible:".cky-consent-container"}],optIn:[{waitForThenClick:".cky-consent-container [data-cky-tag=accept-button]"}],optOut:[{if:{exists:".cky-consent-container [data-cky-tag=reject-button]"},then:[{waitForThenClick:".cky-consent-container [data-cky-tag=reject-button]"}],else:[{if:{exists:".cky-consent-container [data-cky-tag=settings-button]"},then:[{click:".cky-consent-container [data-cky-tag=settings-button]"},{waitFor:".cky-modal-open input[type=checkbox]"},{click:".cky-modal-open input[type=checkbox]:checked",all:!0,optional:!0},{waitForThenClick:".cky-modal [data-cky-tag=detail-save-button]"}],else:[{hide:".cky-consent-container,.cky-overlay"}]}]}],test:[{eval:"EVAL_COOKIEYES_0"}]},{name:"corona-in-zahlen.de",prehideSelectors:[".cookiealert"],detectCmp:[{exists:".cookiealert"}],detectPopup:[{visible:".cookiealert"}],optOut:[{click:".configurecookies"},{click:".confirmcookies"}],optIn:[{click:".acceptcookies"}]},{name:"crossfit-com",cosmetic:!0,prehideSelectors:['body #modal > div > div[class^="_wrapper_"]'],detectCmp:[{exists:'body #modal > div > div[class^="_wrapper_"]'}],detectPopup:[{visible:'body #modal > div > div[class^="_wrapper_"]'}],optIn:[{click:'button[aria-label="accept cookie policy"]'}],optOut:[{hide:'body #modal > div > div[class^="_wrapper_"]'}]},{name:"csu-landtag-de",runContext:{urlPattern:"^https://(www\\.|)?csu-landtag\\.de"},prehideSelectors:["#cookie-disclaimer"],detectCmp:[{exists:"#cookie-disclaimer"}],detectPopup:[{visible:"#cookie-disclaimer"}],optIn:[{click:"#cookieall"}],optOut:[{click:"#cookiesel"}]},{name:"dailymotion-us",cosmetic:!0,prehideSelectors:['div[class*="CookiePopup__desktopContainer"]:has(div[class*="CookiePopup"])'],detectCmp:[{exists:'div[class*="CookiePopup__desktopContainer"]'}],detectPopup:[{visible:'div[class*="CookiePopup__desktopContainer"]'}],optIn:[{click:'div[class*="CookiePopup__desktopContainer"] > button > span'}],optOut:[{hide:'div[class*="CookiePopup__desktopContainer"]'}]},{name:"dailymotion.com",runContext:{urlPattern:"^https://(www\\.)?dailymotion\\.com/"},prehideSelectors:['div[class*="Overlay__container"]:has(div[class*="TCF2Popup"])'],detectCmp:[{exists:'div[class*="TCF2Popup"]'}],detectPopup:[{visible:'[class*="TCF2Popup"] a[href^="https://www.dailymotion.com/legal/cookiemanagement"]'}],optIn:[{waitForThenClick:'button[class*="TCF2Popup__button"]:not([class*="TCF2Popup__personalize"])'}],optOut:[{waitForThenClick:'button[class*="TCF2ContinueWithoutAcceptingButton"]'}],test:[{eval:"EVAL_DAILYMOTION_0"}]},{name:"deepl.com",prehideSelectors:[".dl_cookieBanner_container"],detectCmp:[{exists:".dl_cookieBanner_container"}],detectPopup:[{visible:".dl_cookieBanner_container"}],optOut:[{click:".dl_cookieBanner--buttonSelected"}],optIn:[{click:".dl_cookieBanner--buttonAll"}]},{name:"delta.com",runContext:{urlPattern:"^https://www\\.delta\\.com/"},cosmetic:!0,prehideSelectors:["ngc-cookie-banner"],detectCmp:[{exists:"div.cookie-footer-container"}],detectPopup:[{visible:"div.cookie-footer-container"}],optIn:[{click:" button.cookie-close-icon"}],optOut:[{hide:"div.cookie-footer-container"}]},{name:"dmgmedia-us",prehideSelectors:["#mol-ads-cmp-iframe, div.mol-ads-cmp > form > div"],detectCmp:[{exists:"div.mol-ads-cmp > form > div"}],detectPopup:[{waitForVisible:"div.mol-ads-cmp > form > div"}],optIn:[{waitForThenClick:"button.mol-ads-cmp--btn-primary"}],optOut:[{waitForThenClick:"div.mol-ads-ccpa--message > u > a"},{waitForVisible:".mol-ads-cmp--modal-dialog"},{waitForThenClick:"a.mol-ads-cmp-footer-privacy"},{waitForThenClick:"button.mol-ads-cmp--btn-secondary"}]},{name:"dmgmedia",prehideSelectors:['[data-project="mol-fe-cmp"]'],detectCmp:[{exists:'[data-project="mol-fe-cmp"]'}],detectPopup:[{visible:'[data-project="mol-fe-cmp"]'}],optIn:[{waitForThenClick:'[data-project="mol-fe-cmp"] button[class*=primary]'}],optOut:[{waitForThenClick:'[data-project="mol-fe-cmp"] button[class*=basic]'},{waitForVisible:'[data-project="mol-fe-cmp"] div[class*="tabContent"]'},{waitForThenClick:'[data-project="mol-fe-cmp"] div[class*="toggle"][class*="enabled"]',all:!0},{waitForThenClick:['[data-project="mol-fe-cmp"] [class*=footer]',"xpath///button[contains(., 'Save & Exit')]"]}]},{name:"dndbeyond",vendorUrl:"https://www.dndbeyond.com/",runContext:{urlPattern:"^https://(www\\.)?dndbeyond\\.com/"},prehideSelectors:["[id^=cookie-consent-banner]"],detectCmp:[{exists:"[id^=cookie-consent-banner]"}],detectPopup:[{visible:"[id^=cookie-consent-banner]"}],optIn:[{waitForThenClick:"#cookie-consent-granted"}],optOut:[{waitForThenClick:"#cookie-consent-denied"}],test:[{eval:"EVAL_DNDBEYOND_TEST"}]},{name:"Drupal",detectCmp:[{exists:"#drupalorg-crosssite-gdpr"}],detectPopup:[{visible:"#drupalorg-crosssite-gdpr"}],optOut:[{click:".no"}],optIn:[{click:".yes"}]},{name:"WP DSGVO Tools",link:"https://wordpress.org/plugins/shapepress-dsgvo/",prehideSelectors:[".sp-dsgvo"],cosmetic:!0,detectCmp:[{exists:".sp-dsgvo.sp-dsgvo-popup-overlay"}],detectPopup:[{visible:".sp-dsgvo.sp-dsgvo-popup-overlay",check:"any"}],optIn:[{click:".sp-dsgvo-privacy-btn-accept-all",all:!0}],optOut:[{hide:".sp-dsgvo.sp-dsgvo-popup-overlay"}],test:[{eval:"EVAL_DSGVO_0"}]},{name:"dunelm.com",prehideSelectors:["div[data-testid=cookie-consent-modal-backdrop]"],detectCmp:[{exists:"div[data-testid=cookie-consent-message-contents]"}],detectPopup:[{visible:"div[data-testid=cookie-consent-message-contents]"}],optIn:[{click:'[data-testid="cookie-consent-allow-all"]'}],optOut:[{click:"button[data-testid=cookie-consent-adjust-settings]"},{click:"button[data-testid=cookie-consent-preferences-save]"}],test:[{eval:"EVAL_DUNELM_0"}]},{name:"ebay",vendorUrl:"https://ebay.com",cosmetic:!1,runContext:{main:!0,frame:!1,urlPattern:"^https://(www\\.)?ebay\\.([.a-z]+)/"},prehideSelectors:["#gdpr-banner"],detectCmp:[{exists:"#gdpr-banner"}],detectPopup:[{visible:"#gdpr-banner"}],optIn:[{waitForThenClick:"#gdpr-banner-accept"}],optOut:[{waitForThenClick:"#gdpr-banner-decline"}]},{name:"ecosia",vendorUrl:"https://www.ecosia.org/",runContext:{urlPattern:"^https://www\\.ecosia\\.org/"},prehideSelectors:[".cookie-wrapper"],detectCmp:[{exists:".cookie-wrapper > .cookie-notice"}],detectPopup:[{visible:".cookie-wrapper > .cookie-notice"}],optIn:[{waitForThenClick:"[data-test-id=cookie-notice-accept]"}],optOut:[{waitForThenClick:"[data-test-id=cookie-notice-reject]"}]},{name:"Ensighten ensModal",prehideSelectors:[".ensModal"],detectCmp:[{exists:".ensModal"}],detectPopup:[{visible:"#ensModalWrapper[style*=block]"}],optIn:[{waitForThenClick:"#modalAcceptButton"}],optOut:[{wait:500},{visible:"#ensModalWrapper[style*=block]"},{waitForThenClick:".ensCheckbox:checked",all:!0},{waitForThenClick:"#ensSave"}]},{name:"Ensighten ensNotifyBanner",prehideSelectors:["#ensNotifyBanner"],detectCmp:[{exists:"#ensNotifyBanner"}],detectPopup:[{visible:"#ensNotifyBanner[style*=block]"}],optIn:[{waitForThenClick:"#ensCloseBanner"}],optOut:[{wait:500},{visible:"#ensNotifyBanner[style*=block]"},{waitForThenClick:"#ensRejectAll,#rejectAll,#ensRejectBanner,.rejectAll"}]},{name:"espace-personnel.agirc-arrco.fr",runContext:{urlPattern:"^https://espace-personnel\\.agirc-arrco\\.fr/"},prehideSelectors:[".cdk-overlay-container"],detectCmp:[{exists:".cdk-overlay-container app-esaa-cookie-component"}],detectPopup:[{visible:".cdk-overlay-container app-esaa-cookie-component"}],optIn:[{waitForThenClick:".btn-cookie-accepter"}],optOut:[{waitForThenClick:".btn-cookie-refuser"}]},{name:"etsy",prehideSelectors:["#gdpr-single-choice-overlay","#gdpr-privacy-settings"],detectCmp:[{exists:"#gdpr-single-choice-overlay"}],detectPopup:[{visible:"#gdpr-single-choice-overlay"}],optOut:[{click:"button[data-gdpr-open-full-settings]"},{waitForVisible:".gdpr-overlay-body input",timeout:3e3},{wait:1e3},{eval:"EVAL_ETSY_0"},{eval:"EVAL_ETSY_1"}],optIn:[{click:"button[data-gdpr-single-choice-accept]"}]},{name:"eu-cookie-compliance-banner",detectCmp:[{exists:"body.eu-cookie-compliance-popup-open"}],detectPopup:[{exists:"body.eu-cookie-compliance-popup-open"}],optIn:[{click:".agree-button"}],optOut:[{if:{visible:".decline-button,.eu-cookie-compliance-save-preferences-button"},then:[{click:".decline-button,.eu-cookie-compliance-save-preferences-button"}]},{hide:".eu-cookie-compliance-banner-info, #sliding-popup"}],test:[{eval:"EVAL_EU_COOKIE_COMPLIANCE_0"}]},{name:"EU Cookie Law",prehideSelectors:[".pea_cook_wrapper,.pea_cook_more_info_popover"],cosmetic:!0,detectCmp:[{exists:".pea_cook_wrapper"}],detectPopup:[{wait:500},{visible:".pea_cook_wrapper"}],optIn:[{click:"#pea_cook_btn"}],optOut:[{hide:".pea_cook_wrapper"}],test:[{eval:"EVAL_EU_COOKIE_LAW_0"}]},{name:"europa-eu",vendorUrl:"https://ec.europa.eu/",runContext:{urlPattern:"^https://[^/]*europa\\.eu/"},prehideSelectors:["#cookie-consent-banner"],detectCmp:[{exists:".cck-container"}],detectPopup:[{visible:".cck-container"}],optIn:[{waitForThenClick:'.cck-actions-button[href="#accept"]'}],optOut:[{waitForThenClick:'.cck-actions-button[href="#refuse"]',hide:".cck-container"}]},{name:"EZoic",prehideSelectors:["#ez-cookie-dialog-wrapper"],detectCmp:[{exists:"#ez-cookie-dialog-wrapper"}],detectPopup:[{visible:"#ez-cookie-dialog-wrapper"}],optIn:[{click:"#ez-accept-all",optional:!0},{eval:"EVAL_EZOIC_0",optional:!0}],optOut:[{wait:500},{click:"#ez-manage-settings"},{waitFor:"#ez-cookie-dialog input[type=checkbox]"},{click:"#ez-cookie-dialog input[type=checkbox]:checked",all:!0},{click:"#ez-save-settings"}],test:[{eval:"EVAL_EZOIC_1"}]},{name:"facebook",runContext:{urlPattern:"^https://([a-z0-9-]+\\.)?facebook\\.com/"},prehideSelectors:['div[data-testid="cookie-policy-manage-dialog"]'],detectCmp:[{exists:'div[data-testid="cookie-policy-manage-dialog"]'}],detectPopup:[{visible:'div[data-testid="cookie-policy-manage-dialog"]'}],optIn:[{waitForThenClick:'button[data-cookiebanner="accept_button"]'},{waitForVisible:'div[data-testid="cookie-policy-manage-dialog"]',check:"none"}],optOut:[{waitForThenClick:'button[data-cookiebanner="accept_only_essential_button"]'},{waitForVisible:'div[data-testid="cookie-policy-manage-dialog"]',check:"none"}]},{name:"fides",vendorUrl:"https://github.com/ethyca/fides",prehideSelectors:["#fides-overlay"],detectCmp:[{exists:"#fides-overlay #fides-banner"}],detectPopup:[{visible:"#fides-overlay #fides-banner"},{eval:"EVAL_FIDES_DETECT_POPUP"}],optIn:[{waitForThenClick:"#fides-banner .fides-accept-all-button"}],optOut:[{waitForThenClick:"#fides-banner .fides-reject-all-button"}]},{name:"funding-choices",prehideSelectors:[".fc-consent-root,.fc-dialog-container,.fc-dialog-overlay,.fc-dialog-content"],detectCmp:[{exists:".fc-consent-root"}],detectPopup:[{exists:".fc-dialog-container"}],optOut:[{click:".fc-cta-do-not-consent,.fc-cta-manage-options"},{click:".fc-preference-consent:checked,.fc-preference-legitimate-interest:checked",all:!0,optional:!0},{click:".fc-confirm-choices",optional:!0}],optIn:[{click:".fc-cta-consent"}]},{name:"geeks-for-geeks",runContext:{urlPattern:"^https://www\\.geeksforgeeks\\.org/"},cosmetic:!0,prehideSelectors:[".cookie-consent"],detectCmp:[{exists:".cookie-consent"}],detectPopup:[{visible:".cookie-consent"}],optIn:[{click:".cookie-consent button.consent-btn"}],optOut:[{hide:".cookie-consent"}]},{name:"generic-cosmetic",cosmetic:!0,prehideSelectors:["#js-cookie-banner,.js-cookie-banner,.cookie-banner,#cookie-banner"],detectCmp:[{exists:"#js-cookie-banner,.js-cookie-banner,.cookie-banner,#cookie-banner"}],detectPopup:[{visible:"#js-cookie-banner,.js-cookie-banner,.cookie-banner,#cookie-banner"}],optIn:[],optOut:[{hide:"#js-cookie-banner,.js-cookie-banner,.cookie-banner,#cookie-banner"}]},{name:"google-consent-standalone",prehideSelectors:[],detectCmp:[{exists:'a[href^="https://policies.google.com/technologies/cookies"'},{exists:'form[action^="https://consent.google."][action$=".com/save"]'}],detectPopup:[{visible:'a[href^="https://policies.google.com/technologies/cookies"'}],optIn:[{waitForThenClick:'form[action^="https://consent.google."][action$=".com/save"]:has(input[name=set_eom][value=false]) button'}],optOut:[{waitForThenClick:'form[action^="https://consent.google."][action$=".com/save"]:has(input[name=set_eom][value=true]) button'}]},{name:"google.com",prehideSelectors:[".HTjtHe#xe7COe"],detectCmp:[{exists:".HTjtHe#xe7COe"},{exists:'.HTjtHe#xe7COe a[href^="https://policies.google.com/technologies/cookies"]'}],detectPopup:[{visible:".HTjtHe#xe7COe button#W0wltc"}],optIn:[{waitForThenClick:".HTjtHe#xe7COe button#L2AGLb"}],optOut:[{waitForThenClick:".HTjtHe#xe7COe button#W0wltc"}],test:[{eval:"EVAL_GOOGLE_0"}]},{name:"gov.uk",detectCmp:[{exists:"#global-cookie-message"}],detectPopup:[{exists:"#global-cookie-message"}],optIn:[{click:"button[data-accept-cookies=true]"}],optOut:[{click:"button[data-reject-cookies=true],#reject-cookies"},{click:"button[data-hide-cookie-banner=true],#hide-cookie-decision"}]},{name:"hashicorp",vendorUrl:"https://hashicorp.com/",runContext:{urlPattern:"^https://[^.]*\\.hashicorp\\.com/"},prehideSelectors:["[data-testid=consent-banner]"],detectCmp:[{exists:"[data-testid=consent-banner]"}],detectPopup:[{visible:"[data-testid=consent-banner]"}],optIn:[{waitForThenClick:"[data-testid=accept]"}],optOut:[{waitForThenClick:"[data-testid=manage-preferences]"},{waitForThenClick:"[data-testid=consent-mgr-dialog] [data-ga-button=save-preferences]"}]},{name:"healthline-media",prehideSelectors:["#modal-host > div.no-hash > div.window-wrapper"],detectCmp:[{exists:"#modal-host > div.no-hash > div.window-wrapper, div[data-testid=qualtrics-container]"}],detectPopup:[{exists:"#modal-host > div.no-hash > div.window-wrapper, div[data-testid=qualtrics-container]"}],optIn:[{click:"#modal-host > div.no-hash > div.window-wrapper > div:last-child button"}],optOut:[{if:{exists:'#modal-host > div.no-hash > div.window-wrapper > div:last-child a[href="/privacy-settings"]'},then:[{click:'#modal-host > div.no-hash > div.window-wrapper > div:last-child a[href="/privacy-settings"]'}],else:[{waitForVisible:"div#__next"},{click:"#__next div:nth-child(1) > button:first-child"}]}]},{name:"hema",prehideSelectors:[".cookie-modal"],detectCmp:[{visible:".cookie-modal .cookie-accept-btn"}],detectPopup:[{visible:".cookie-modal .cookie-accept-btn"}],optIn:[{waitForThenClick:".cookie-modal .cookie-accept-btn"}],optOut:[{waitForThenClick:".cookie-modal .js-cookie-reject-btn"}],test:[{eval:"EVAL_HEMA_TEST_0"}]},{name:"hetzner.com",runContext:{urlPattern:"^https://www\\.hetzner\\.com/"},prehideSelectors:["#CookieConsent"],detectCmp:[{exists:"#CookieConsent"}],detectPopup:[{visible:"#CookieConsent"}],optIn:[{click:"#CookieConsentGiven"}],optOut:[{click:"#CookieConsentDeclined"}]},{name:"hl.co.uk",prehideSelectors:[".cookieModalContent","#cookie-banner-overlay"],detectCmp:[{exists:"#cookie-banner-overlay"}],detectPopup:[{exists:"#cookie-banner-overlay"}],optIn:[{click:"#acceptCookieButton"}],optOut:[{click:"#manageCookie"},{hide:".cookieSettingsModal"},{waitFor:"#AOCookieToggle"},{click:"#AOCookieToggle[aria-pressed=true]",optional:!0},{waitFor:"#TPCookieToggle"},{click:"#TPCookieToggle[aria-pressed=true]",optional:!0},{click:"#updateCookieButton"}]},{name:"hu-manity",vendorUrl:"https://hu-manity.co/",prehideSelectors:["#hu.hu-wrapper"],detectCmp:[{exists:"#hu.hu-visible"}],detectPopup:[{visible:"#hu.hu-visible"}],optIn:[{waitForThenClick:"[data-hu-action=cookies-notice-consent-choices-3]"},{waitForThenClick:"#hu-cookies-save"}],optOut:[{waitForThenClick:"#hu-cookies-save"}]},{name:"hubspot",detectCmp:[{exists:"#hs-eu-cookie-confirmation"}],detectPopup:[{visible:"#hs-eu-cookie-confirmation"}],optIn:[{click:"#hs-eu-confirmation-button"}],optOut:[{click:"#hs-eu-decline-button"}]},{name:"indeed.com",cosmetic:!0,prehideSelectors:["#CookiePrivacyNotice"],detectCmp:[{exists:"#CookiePrivacyNotice"}],detectPopup:[{visible:"#CookiePrivacyNotice"}],optIn:[{click:"#CookiePrivacyNotice button[data-gnav-element-name=CookiePrivacyNoticeOk]"}],optOut:[{hide:"#CookiePrivacyNotice"}]},{name:"ing.de",runContext:{urlPattern:"^https://www\\.ing\\.de/"},cosmetic:!0,prehideSelectors:['div[slot="backdrop"]'],detectCmp:[{exists:'[data-tag-name="ing-cc-dialog-frame"]'}],detectPopup:[{visible:'[data-tag-name="ing-cc-dialog-frame"]'}],optIn:[{click:['[data-tag-name="ing-cc-dialog-level0"]','[data-tag-name="ing-cc-button"][class*="accept"]']}],optOut:[{click:['[data-tag-name="ing-cc-dialog-level0"]','[data-tag-name="ing-cc-button"][class*="more"]']}]},{name:"instagram",vendorUrl:"https://instagram.com",runContext:{urlPattern:"^https://www\\.instagram\\.com/"},prehideSelectors:[".x78zum5.xdt5ytf.xg6iff7.x1n2onr6:has(._a9--)"],detectCmp:[{exists:".x1qjc9v5.x9f619.x78zum5.xdt5ytf.x1iyjqo2.xl56j7k"}],detectPopup:[{visible:".x1qjc9v5.x9f619.x78zum5.xdt5ytf.x1iyjqo2.xl56j7k"}],optIn:[{waitForThenClick:"._a9--._a9_0"}],optOut:[{waitForThenClick:"._a9--._a9_1"},{wait:2e3}]},{name:"ionos.de",prehideSelectors:[".privacy-consent--backdrop",".privacy-consent--modal"],detectCmp:[{exists:".privacy-consent--modal"}],detectPopup:[{visible:".privacy-consent--modal"}],optIn:[{click:"#selectAll"}],optOut:[{click:".footer-config-link"},{click:"#confirmSelection"}]},{name:"itopvpn.com",cosmetic:!0,prehideSelectors:[".pop-cookie"],detectCmp:[{exists:".pop-cookie"}],detectPopup:[{exists:".pop-cookie"}],optIn:[{click:"#_pcookie"}],optOut:[{hide:".pop-cookie"}]},{name:"iubenda",prehideSelectors:["#iubenda-cs-banner"],detectCmp:[{exists:"#iubenda-cs-banner"}],detectPopup:[{visible:".iubenda-cs-accept-btn"}],optIn:[{waitForThenClick:".iubenda-cs-accept-btn"}],optOut:[{waitForThenClick:".iubenda-cs-customize-btn"},{eval:"EVAL_IUBENDA_0"},{waitForThenClick:"#iubFooterBtn"}],test:[{eval:"EVAL_IUBENDA_1"}]},{name:"iWink",prehideSelectors:["body.cookies-request #cookie-bar"],detectCmp:[{exists:"body.cookies-request #cookie-bar"}],detectPopup:[{visible:"body.cookies-request #cookie-bar"}],optIn:[{waitForThenClick:"body.cookies-request #cookie-bar .allow-cookies"}],optOut:[{waitForThenClick:"body.cookies-request #cookie-bar .disallow-cookies"}],test:[{eval:"EVAL_IWINK_TEST"}]},{name:"jdsports",vendorUrl:"https://www.jdsports.co.uk/",runContext:{urlPattern:"^https://(www|m)\\.jdsports\\."},prehideSelectors:[".miniConsent,#PrivacyPolicyBanner"],detectCmp:[{exists:".miniConsent,#PrivacyPolicyBanner"}],detectPopup:[{visible:".miniConsent,#PrivacyPolicyBanner"}],optIn:[{waitForThenClick:".miniConsent .accept-all-cookies"}],optOut:[{if:{exists:"#PrivacyPolicyBanner"},then:[{hide:"#PrivacyPolicyBanner"}],else:[{waitForThenClick:"#cookie-settings"},{waitForThenClick:"#reject-all-cookies"}]}]},{name:"johnlewis.com",prehideSelectors:["div[class^=pecr-cookie-banner-]"],detectCmp:[{exists:"div[class^=pecr-cookie-banner-]"}],detectPopup:[{exists:"div[class^=pecr-cookie-banner-]"}],optOut:[{click:"button[data-test^=manage-cookies]"},{wait:"500"},{click:"label[data-test^=toggle][class*=checked]:not([class*=disabled])",all:!0,optional:!0},{click:"button[data-test=save-preferences]"}],optIn:[{click:"button[data-test=allow-all]"}]},{name:"jquery.cookieBar",vendorUrl:"https://github.com/kovarp/jquery.cookieBar",prehideSelectors:[".cookie-bar"],cosmetic:!0,detectCmp:[{exists:".cookie-bar .cookie-bar__message,.cookie-bar .cookie-bar__buttons"}],detectPopup:[{visible:".cookie-bar .cookie-bar__message,.cookie-bar .cookie-bar__buttons",check:"any"}],optIn:[{click:".cookie-bar .cookie-bar__btn"}],optOut:[{hide:".cookie-bar"}],test:[{visible:".cookie-bar .cookie-bar__message,.cookie-bar .cookie-bar__buttons",check:"none"},{eval:"EVAL_JQUERY_COOKIEBAR_0"}]},{name:"justwatch.com",prehideSelectors:[".consent-banner"],detectCmp:[{exists:".consent-banner .consent-banner__actions"}],detectPopup:[{visible:".consent-banner .consent-banner__actions"}],optIn:[{click:".consent-banner__actions button.basic-button.primary"}],optOut:[{click:".consent-banner__actions button.basic-button.secondary"},{waitForThenClick:".consent-modal__footer button.basic-button.secondary"},{waitForThenClick:".consent-modal ion-content > div > a:nth-child(9)"},{click:"label.consent-switch input[type=checkbox]:checked",all:!0,optional:!0},{waitForVisible:".consent-modal__footer button.basic-button.primary"},{click:".consent-modal__footer button.basic-button.primary"}]},{name:"ketch",vendorUrl:"https://www.ketch.com",runContext:{frame:!1,main:!0},intermediate:!1,prehideSelectors:["#lanyard_root div[role='dialog']"],detectCmp:[{exists:"#lanyard_root div[role='dialog']"}],detectPopup:[{visible:"#lanyard_root div[role='dialog']"}],optIn:[{if:{exists:"#lanyard_root button[class='confirmButton']"},then:[{waitForThenClick:"#lanyard_root div[class*=buttons] > :nth-child(2)"},{click:"#lanyard_root button[class='confirmButton']"}],else:[{waitForThenClick:"#lanyard_root div[class*=buttons] > :nth-child(2)"}]}],optOut:[{if:{exists:"#lanyard_root [aria-describedby=banner-description]"},then:[{waitForThenClick:"#lanyard_root div[class*=buttons] > button[class*=secondaryButton], #lanyard_root button[class*=buttons-secondary]",comment:"can be either settings or reject button"}]},{waitFor:"#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description], #ketch-preferences",timeout:1e3,optional:!0},{if:{exists:"#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description], #ketch-preferences"},then:[{waitForThenClick:"#lanyard_root button[class*=rejectButton], #lanyard_root button[class*=rejectAllButton]"},{click:"#lanyard_root button[class*=confirmButton],#lanyard_root div[class*=actions_] > button:nth-child(1), #lanyard_root button[class*=actionButton]"}]}],test:[{eval:"EVAL_KETCH_TEST"}]},{name:"kleinanzeigen-de",runContext:{urlPattern:"^https?://(www\\.)?kleinanzeigen\\.de"},prehideSelectors:["#gdpr-banner-container"],detectCmp:[{any:[{exists:"#gdpr-banner-container #gdpr-banner [data-testid=gdpr-banner-cmp-button]"},{exists:"#ConsentManagementPage"}]}],detectPopup:[{any:[{visible:"#gdpr-banner-container #gdpr-banner [data-testid=gdpr-banner-cmp-button]"},{visible:"#ConsentManagementPage"}]}],optIn:[{if:{exists:"#gdpr-banner-container #gdpr-banner"},then:[{click:"#gdpr-banner-container #gdpr-banner [data-testid=gdpr-banner-accept]"}],else:[{click:"#ConsentManagementPage .Button-primary"}]}],optOut:[{if:{exists:"#gdpr-banner-container #gdpr-banner"},then:[{click:"#gdpr-banner-container #gdpr-banner [data-testid=gdpr-banner-cmp-button]"}],else:[{click:"#ConsentManagementPage .Button-secondary"}]}]},{name:"lightbox",prehideSelectors:[".darken-layer.open,.lightbox.lightbox--cookie-consent"],detectCmp:[{exists:"body.cookie-consent-is-active div.lightbox--cookie-consent > div.lightbox__content > div.cookie-consent[data-jsb]"}],detectPopup:[{visible:"body.cookie-consent-is-active div.lightbox--cookie-consent > div.lightbox__content > div.cookie-consent[data-jsb]"}],optOut:[{click:".cookie-consent__footer > button[type='submit']:not([data-button='selectAll'])"}],optIn:[{click:".cookie-consent__footer > button[type='submit'][data-button='selectAll']"}]},{name:"lineagrafica",vendorUrl:"https://addons.prestashop.com/en/legal/8734-eu-cookie-law-gdpr-banner-blocker.html",cosmetic:!0,prehideSelectors:["#lgcookieslaw_banner,#lgcookieslaw_modal,.lgcookieslaw-overlay"],detectCmp:[{exists:"#lgcookieslaw_banner,#lgcookieslaw_modal,.lgcookieslaw-overlay"}],detectPopup:[{exists:"#lgcookieslaw_banner,#lgcookieslaw_modal,.lgcookieslaw-overlay"}],optIn:[{waitForThenClick:"#lgcookieslaw_accept"}],optOut:[{hide:"#lgcookieslaw_banner,#lgcookieslaw_modal,.lgcookieslaw-overlay"}]},{name:"linkedin.com",prehideSelectors:[".artdeco-global-alert[type=COOKIE_CONSENT]"],detectCmp:[{exists:".artdeco-global-alert[type=COOKIE_CONSENT]"}],detectPopup:[{visible:".artdeco-global-alert[type=COOKIE_CONSENT]"}],optIn:[{waitForVisible:".artdeco-global-alert[type=COOKIE_CONSENT] button[action-type=ACCEPT]"},{wait:500},{waitForThenClick:".artdeco-global-alert[type=COOKIE_CONSENT] button[action-type=ACCEPT]"}],optOut:[{waitForVisible:".artdeco-global-alert[type=COOKIE_CONSENT] button[action-type=DENY]"},{wait:500},{waitForThenClick:".artdeco-global-alert[type=COOKIE_CONSENT] button[action-type=DENY]"}],test:[{waitForVisible:".artdeco-global-alert[type=COOKIE_CONSENT]",check:"none"}]},{name:"livejasmin",vendorUrl:"https://www.livejasmin.com/",runContext:{urlPattern:"^https://(m|www)\\.livejasmin\\.com/"},prehideSelectors:["#consent_modal"],detectCmp:[{exists:"#consent_modal"}],detectPopup:[{visible:"#consent_modal"}],optIn:[{waitForThenClick:"#consent_modal button[data-testid=ButtonStyledButton]:first-of-type"}],optOut:[{waitForThenClick:"#consent_modal button[data-testid=ButtonStyledButton]:nth-of-type(2)"},{waitForVisible:"[data-testid=PrivacyPreferenceCenterWithConsentCookieContent]"},{click:"[data-testid=PrivacyPreferenceCenterWithConsentCookieContent] input[data-testid=PrivacyPreferenceCenterWithConsentCookieSwitch]:checked",optional:!0,all:!0},{waitForThenClick:"[data-testid=PrivacyPreferenceCenterWithConsentCookieContent] button[data-testid=ButtonStyledButton]:last-child"}]},{name:"macpaw.com",cosmetic:!0,prehideSelectors:['div[data-banner="cookies"]'],detectCmp:[{exists:'div[data-banner="cookies"]'}],detectPopup:[{exists:'div[data-banner="cookies"]'}],optIn:[{click:'button[data-banner-close="cookies"]'}],optOut:[{hide:'div[data-banner="cookies"]'}]},{name:"marksandspencer.com",cosmetic:!0,detectCmp:[{exists:".navigation-cookiebbanner"}],detectPopup:[{visible:".navigation-cookiebbanner"}],optOut:[{hide:".navigation-cookiebbanner"}],optIn:[{click:".navigation-cookiebbanner__submit"}]},{name:"mediamarkt.de",prehideSelectors:["div[aria-labelledby=pwa-consent-layer-title]","div[class^=StyledConsentLayerWrapper-]"],detectCmp:[{exists:"div[aria-labelledby^=pwa-consent-layer-title]"}],detectPopup:[{exists:"div[aria-labelledby^=pwa-consent-layer-title]"}],optOut:[{click:"button[data-test^=pwa-consent-layer-deny-all]"}],optIn:[{click:"button[data-test^=pwa-consent-layer-accept-all"}]},{name:"Mediavine",prehideSelectors:['[data-name="mediavine-gdpr-cmp"]'],detectCmp:[{exists:'[data-name="mediavine-gdpr-cmp"]'}],detectPopup:[{wait:500},{visible:'[data-name="mediavine-gdpr-cmp"]'}],optIn:[{waitForThenClick:'[data-name="mediavine-gdpr-cmp"] [format="primary"]'}],optOut:[{waitForThenClick:'[data-name="mediavine-gdpr-cmp"] [data-view="manageSettings"]'},{waitFor:'[data-name="mediavine-gdpr-cmp"] input[type=checkbox]'},{eval:"EVAL_MEDIAVINE_0",optional:!0},{click:'[data-name="mediavine-gdpr-cmp"] [format="secondary"]'}]},{name:"microsoft.com",prehideSelectors:["#wcpConsentBannerCtrl"],detectCmp:[{exists:"#wcpConsentBannerCtrl"}],detectPopup:[{exists:"#wcpConsentBannerCtrl"}],optOut:[{eval:"EVAL_MICROSOFT_0"}],optIn:[{eval:"EVAL_MICROSOFT_1"}],test:[{eval:"EVAL_MICROSOFT_2"}]},{name:"midway-usa",runContext:{urlPattern:"^https://www\\.midwayusa\\.com/"},cosmetic:!0,prehideSelectors:["#cookie-container"],detectCmp:[{exists:['div[aria-label="Cookie Policy Banner"]']}],detectPopup:[{visible:"#cookie-container"}],optIn:[{click:"button#cookie-btn"}],optOut:[{hide:'div[aria-label="Cookie Policy Banner"]'}]},{name:"moneysavingexpert.com",detectCmp:[{exists:"dialog[data-testid=accept-our-cookies-dialog]"}],detectPopup:[{visible:"dialog[data-testid=accept-our-cookies-dialog]"}],optIn:[{click:"#banner-accept"}],optOut:[{click:"#banner-manage"},{click:"#pc-confirm"}]},{name:"monzo.com",prehideSelectors:[".cookie-alert, cookie-alert__content"],detectCmp:[{exists:'div.cookie-alert[role="dialog"]'},{exists:'a[href*="monzo"]'}],detectPopup:[{visible:".cookie-alert__content"}],optIn:[{click:".js-accept-cookie-policy"}],optOut:[{click:".js-decline-cookie-policy"}]},{name:"Moove",prehideSelectors:["#moove_gdpr_cookie_info_bar"],detectCmp:[{exists:"#moove_gdpr_cookie_info_bar"}],detectPopup:[{visible:"#moove_gdpr_cookie_info_bar:not(.moove-gdpr-info-bar-hidden)"}],optIn:[{waitForThenClick:".moove-gdpr-infobar-allow-all"}],optOut:[{if:{exists:"#moove_gdpr_cookie_info_bar .change-settings-button"},then:[{click:"#moove_gdpr_cookie_info_bar .change-settings-button"},{waitForVisible:"#moove_gdpr_cookie_modal"},{eval:"EVAL_MOOVE_0"},{click:".moove-gdpr-modal-save-settings"}],else:[{hide:"#moove_gdpr_cookie_info_bar"}]}],test:[{visible:"#moove_gdpr_cookie_info_bar",check:"none"}]},{name:"national-lottery.co.uk",detectCmp:[{exists:".cuk_cookie_consent"}],detectPopup:[{visible:".cuk_cookie_consent",check:"any"}],optOut:[{click:".cuk_cookie_consent_manage_pref"},{click:".cuk_cookie_consent_save_pref"},{click:".cuk_cookie_consent_close"}],optIn:[{click:".cuk_cookie_consent_accept_all"}]},{name:"nba.com",runContext:{urlPattern:"^https://(www\\.)?nba.com/"},cosmetic:!0,prehideSelectors:["#onetrust-banner-sdk"],detectCmp:[{exists:"#onetrust-banner-sdk"}],detectPopup:[{visible:"#onetrust-banner-sdk"}],optIn:[{click:"#onetrust-accept-btn-handler"}],optOut:[{hide:"#onetrust-banner-sdk"}]},{name:"netflix.de",detectCmp:[{exists:"#cookie-disclosure"}],detectPopup:[{visible:".cookie-disclosure-message",check:"any"}],optIn:[{click:".btn-accept"}],optOut:[{hide:"#cookie-disclosure"},{click:".btn-reject"}]},{name:"nhs.uk",prehideSelectors:["#nhsuk-cookie-banner"],detectCmp:[{exists:"#nhsuk-cookie-banner"}],detectPopup:[{exists:"#nhsuk-cookie-banner"}],optOut:[{click:"#nhsuk-cookie-banner__link_accept"}],optIn:[{click:"#nhsuk-cookie-banner__link_accept_analytics"}]},{name:"notice-cookie",prehideSelectors:[".button--notice"],cosmetic:!0,detectCmp:[{exists:".notice--cookie"}],detectPopup:[{visible:".notice--cookie"}],optIn:[{click:".button--notice"}],optOut:[{hide:".notice--cookie"}]},{name:"nrk.no",cosmetic:!0,prehideSelectors:[".nrk-masthead__info-banner--cookie"],detectCmp:[{exists:".nrk-masthead__info-banner--cookie"}],detectPopup:[{exists:".nrk-masthead__info-banner--cookie"}],optIn:[{click:"div.nrk-masthead__info-banner--cookie button > span:has(+ svg.nrk-close)"}],optOut:[{hide:".nrk-masthead__info-banner--cookie"}]},{name:"obi.de",prehideSelectors:[".disc-cp--active"],detectCmp:[{exists:".disc-cp-modal__modal"}],detectPopup:[{visible:".disc-cp-modal__modal"}],optIn:[{click:".js-disc-cp-accept-all"}],optOut:[{click:".js-disc-cp-deny-all"}]},{name:"om",vendorUrl:"https://olli-machts.de/en/extension/cookie-manager",prehideSelectors:[".tx-om-cookie-consent"],detectCmp:[{exists:".tx-om-cookie-consent .active[data-omcookie-panel]"}],detectPopup:[{exists:".tx-om-cookie-consent .active[data-omcookie-panel]"}],optIn:[{waitForThenClick:"[data-omcookie-panel-save=all]"}],optOut:[{if:{exists:"[data-omcookie-panel-save=min]"},then:[{waitForThenClick:"[data-omcookie-panel-save=min]"}],else:[{click:"input[data-omcookie-panel-grp]:checked:not(:disabled)",all:!0,optional:!0},{waitForThenClick:"[data-omcookie-panel-save=save]"}]}]},{name:"onlyFans.com",runContext:{urlPattern:"^https://onlyfans\\.com/"},prehideSelectors:["div.b-cookies-informer"],detectCmp:[{exists:"div.b-cookies-informer"}],detectPopup:[{exists:"div.b-cookies-informer"}],optIn:[{click:"div.b-cookies-informer__nav > button:nth-child(2)"}],optOut:[{click:"div.b-cookies-informer__nav > button:nth-child(1)"},{if:{exists:"div.b-cookies-informer__switchers"},then:[{click:"div.b-cookies-informer__switchers input:not([disabled])",all:!0},{click:"div.b-cookies-informer__nav > button"}]}]},{name:"openli",vendorUrl:"https://openli.com",prehideSelectors:[".legalmonster-cleanslate"],detectCmp:[{exists:".legalmonster-cleanslate"}],detectPopup:[{visible:".legalmonster-cleanslate #lm-cookie-wall-container",check:"any"}],optIn:[{waitForThenClick:"#lm-accept-all"}],optOut:[{waitForThenClick:"#lm-accept-necessary"}]},{name:"opera.com",vendorUrl:"https://unknown",cosmetic:!1,runContext:{main:!0,frame:!1},intermediate:!1,prehideSelectors:[],detectCmp:[{exists:"#cookie-consent .manage-cookies__btn"}],detectPopup:[{visible:"#cookie-consent .cookie-basic-consent__btn"}],optIn:[{waitForThenClick:"#cookie-consent .cookie-basic-consent__btn"}],optOut:[{waitForThenClick:"#cookie-consent .manage-cookies__btn"},{waitForThenClick:"#cookie-consent .active.marketing_option_switch.cookie-consent__switch",all:!0},{waitForThenClick:"#cookie-consent .cookie-selection__btn"}],test:[{eval:"EVAL_OPERA_0"}]},{name:"osano",prehideSelectors:[".osano-cm-window,.osano-cm-dialog"],detectCmp:[{exists:".osano-cm-window"}],detectPopup:[{visible:".osano-cm-dialog"}],optIn:[{click:".osano-cm-accept-all",optional:!0}],optOut:[{waitForThenClick:".osano-cm-denyAll"}]},{name:"otto.de",prehideSelectors:[".cookieBanner--visibility"],detectCmp:[{exists:".cookieBanner--visibility"}],detectPopup:[{visible:".cookieBanner__wrapper"}],optIn:[{click:".js_cookieBannerPermissionButton"}],optOut:[{click:".js_cookieBannerProhibitionButton"}]},{name:"ourworldindata",vendorUrl:"https://ourworldindata.org/",runContext:{urlPattern:"^https://ourworldindata\\.org/"},prehideSelectors:[".cookie-manager"],detectCmp:[{exists:".cookie-manager"}],detectPopup:[{visible:".cookie-manager .cookie-notice.open"}],optIn:[{waitForThenClick:".cookie-notice [data-test=accept]"}],optOut:[{waitForThenClick:".cookie-notice [data-test=reject]"}]},{name:"pabcogypsum",vendorUrl:"https://unknown",prehideSelectors:[".js-cookie-notice:has(#cookie_settings-form)"],detectCmp:[{exists:".js-cookie-notice #cookie_settings-form"}],detectPopup:[{visible:".js-cookie-notice #cookie_settings-form"}],optIn:[{waitForThenClick:".js-cookie-notice button[value=allow]"}],optOut:[{waitForThenClick:".js-cookie-notice button[value=disable]"}]},{name:"paypal-us",prehideSelectors:["#ccpaCookieContent_wrapper, article.ppvx_modal--overpanel"],detectCmp:[{exists:"#ccpaCookieBanner, .privacy-sheet-content"}],detectPopup:[{exists:"#ccpaCookieBanner, .privacy-sheet-content"}],optIn:[{click:"#acceptAllButton"}],optOut:[{if:{exists:"a#manageCookiesLink"},then:[{click:"a#manageCookiesLink"}],else:[{waitForVisible:".privacy-sheet-content #formContent"},{click:"#formContent .cookiepref-11m2iee-checkbox_base input:checked",all:!0,optional:!0},{click:".confirmCookie #submitCookiesBtn"}]}]},{name:"paypal.com",prehideSelectors:["#gdprCookieBanner"],detectCmp:[{exists:"#gdprCookieBanner"}],detectPopup:[{visible:"#gdprCookieContent_wrapper"}],optIn:[{click:"#acceptAllButton"}],optOut:[{wait:200},{click:".gdprCookieBanner_decline-button"}],test:[{wait:500},{eval:"EVAL_PAYPAL_0"}]},{name:"pinetools.com",cosmetic:!0,prehideSelectors:["#aviso_cookies"],detectCmp:[{exists:"#aviso_cookies"}],detectPopup:[{exists:".lang_en #aviso_cookies"}],optIn:[{click:"#aviso_cookies .a_boton_cerrar"}],optOut:[{hide:"#aviso_cookies"}]},{name:"pmc",cosmetic:!0,prehideSelectors:["#pmc-pp-tou--notice"],detectCmp:[{exists:"#pmc-pp-tou--notice"}],detectPopup:[{visible:"#pmc-pp-tou--notice"}],optIn:[{click:"span.pmc-pp-tou--notice-close-btn"}],optOut:[{hide:"#pmc-pp-tou--notice"}]},{name:"pornhub.com",runContext:{urlPattern:"^https://(www\\.)?pornhub\\.com/"},cosmetic:!0,prehideSelectors:[".cookiesBanner"],detectCmp:[{exists:".cookiesBanner"}],detectPopup:[{visible:".cookiesBanner"}],optIn:[{click:".cookiesBanner .okButton"}],optOut:[{hide:".cookiesBanner"}]},{name:"pornpics.com",cosmetic:!0,prehideSelectors:["#cookie-contract"],detectCmp:[{exists:"#cookie-contract"}],detectPopup:[{visible:"#cookie-contract"}],optIn:[{click:"#cookie-contract .icon-cross"}],optOut:[{hide:"#cookie-contract"}]},{name:"PrimeBox CookieBar",prehideSelectors:["#cookie-bar"],detectCmp:[{exists:"#cookie-bar .cb-enable,#cookie-bar .cb-disable,#cookie-bar .cb-policy"}],detectPopup:[{visible:"#cookie-bar .cb-enable,#cookie-bar .cb-disable,#cookie-bar .cb-policy",check:"any"}],optIn:[{waitForThenClick:"#cookie-bar .cb-enable"}],optOut:[{click:"#cookie-bar .cb-disable",optional:!0},{hide:"#cookie-bar"}],test:[{eval:"EVAL_PRIMEBOX_0"}]},{name:"privacymanager.io",prehideSelectors:["#gdpr-consent-tool-wrapper",'iframe[src^="https://cmp-consent-tool.privacymanager.io"]'],runContext:{urlPattern:"^https://cmp-consent-tool\\.privacymanager\\.io/",main:!1,frame:!0},detectCmp:[{exists:"button#save"}],detectPopup:[{visible:"button#save"}],optIn:[{click:"button#save"}],optOut:[{if:{exists:"#denyAll"},then:[{click:"#denyAll"},{waitForThenClick:".okButton"}],else:[{waitForThenClick:"#manageSettings"},{waitFor:".purposes-overview-list"},{waitFor:"button#saveAndExit"},{click:"span[role=checkbox][aria-checked=true]",all:!0,optional:!0},{click:"button#saveAndExit"}]}]},{name:"productz.com",vendorUrl:"https://productz.com/",runContext:{urlPattern:"^https://productz\\.com/"},prehideSelectors:[],detectCmp:[{exists:".c-modal.is-active"}],detectPopup:[{visible:".c-modal.is-active"}],optIn:[{waitForThenClick:".c-modal.is-active .is-accept"}],optOut:[{waitForThenClick:".c-modal.is-active .is-dismiss"}]},{name:"pubtech",prehideSelectors:["#pubtech-cmp"],detectCmp:[{exists:"#pubtech-cmp"}],detectPopup:[{visible:"#pubtech-cmp #pt-actions"}],optIn:[{if:{exists:"#pt-accept-all"},then:[{click:"#pubtech-cmp #pt-actions #pt-accept-all"}],else:[{click:"#pubtech-cmp #pt-actions button:nth-of-type(2)"}]}],optOut:[{click:"#pubtech-cmp #pt-close"}],test:[{eval:"EVAL_PUBTECH_0"}]},{name:"quantcast",prehideSelectors:["#qc-cmp2-main,#qc-cmp2-container"],detectCmp:[{exists:"#qc-cmp2-container"}],detectPopup:[{visible:"#qc-cmp2-ui"}],optOut:[{click:'.qc-cmp2-summary-buttons > button[mode="secondary"]'},{waitFor:"#qc-cmp2-ui"},{click:'.qc-cmp2-toggle-switch > button[aria-checked="true"]',all:!0,optional:!0},{click:'.qc-cmp2-main button[aria-label="REJECT ALL"]',optional:!0},{waitForThenClick:'.qc-cmp2-main button[aria-label="SAVE & EXIT"],.qc-cmp2-buttons-desktop > button[mode="primary"]',timeout:5e3}],optIn:[{click:'.qc-cmp2-summary-buttons > button[mode="primary"]'}]},{name:"reddit.com",runContext:{urlPattern:"^https://www\\.reddit\\.com/"},prehideSelectors:["[bundlename=reddit_cookie_banner]"],detectCmp:[{exists:"reddit-cookie-banner"}],detectPopup:[{visible:"reddit-cookie-banner"}],optIn:[{waitForThenClick:["reddit-cookie-banner","#accept-all-cookies-button > button"]}],optOut:[{waitForThenClick:["reddit-cookie-banner","#reject-nonessential-cookies-button > button"]}],test:[{eval:"EVAL_REDDIT_0"}]},{name:"roblox",vendorUrl:"https://roblox.com",cosmetic:!1,runContext:{main:!0,frame:!1,urlPattern:"^https://(www\\.)?roblox\\.com/"},prehideSelectors:[],detectCmp:[{exists:".cookie-banner-wrapper"}],detectPopup:[{visible:".cookie-banner-wrapper .cookie-banner"}],optIn:[{waitForThenClick:".cookie-banner-wrapper button.btn-cta-lg"}],optOut:[{waitForThenClick:".cookie-banner-wrapper button.btn-secondary-lg"}],test:[{eval:"EVAL_ROBLOX_TEST"}]},{name:"rog-forum.asus.com",runContext:{urlPattern:"^https://rog-forum\\.asus\\.com/"},prehideSelectors:["#cookie-policy-info"],detectCmp:[{exists:"#cookie-policy-info"}],detectPopup:[{visible:"#cookie-policy-info"}],optIn:[{click:'div.cookie-btn-box > div[aria-label="Accept"]'}],optOut:[{click:'div.cookie-btn-box > div[aria-label="Reject"]'},{waitForThenClick:'.cookie-policy-lightbox-bottom > div[aria-label="Save Settings"]'}]},{name:"roofingmegastore.co.uk",runContext:{urlPattern:"^https://(www\\.)?roofingmegastore\\.co\\.uk"},prehideSelectors:["#m-cookienotice"],detectCmp:[{exists:"#m-cookienotice"}],detectPopup:[{visible:"#m-cookienotice"}],optIn:[{click:"#accept-cookies"}],optOut:[{click:"#manage-cookies"},{waitForThenClick:"#accept-selected"}]},{name:"samsung.com",runContext:{urlPattern:"^https://www\\.samsung\\.com/"},cosmetic:!0,prehideSelectors:["div.cookie-bar"],detectCmp:[{exists:"div.cookie-bar"}],detectPopup:[{visible:"div.cookie-bar"}],optIn:[{click:"div.cookie-bar__manage > a"}],optOut:[{hide:"div.cookie-bar"}]},{name:"setapp.com",vendorUrl:"https://setapp.com/",cosmetic:!0,runContext:{urlPattern:"^https://setapp\\.com/"},prehideSelectors:[],detectCmp:[{exists:".cookie-banner.js-cookie-banner"}],detectPopup:[{visible:".cookie-banner.js-cookie-banner"}],optIn:[{waitForThenClick:".cookie-banner.js-cookie-banner button"}],optOut:[{hide:".cookie-banner.js-cookie-banner"}]},{name:"sibbo",prehideSelectors:["sibbo-cmp-layout"],detectCmp:[{exists:"sibbo-cmp-layout"}],detectPopup:[{visible:"#rejectAllMain"}],optIn:[{click:"#acceptAllMain"}],optOut:[{click:"#rejectAllMain"}]},{name:"similarweb.com",cosmetic:!0,prehideSelectors:[".app-cookies-notification"],detectCmp:[{exists:".app-cookies-notification"}],detectPopup:[{exists:".app-layout .app-cookies-notification"}],optIn:[{click:"button.app-cookies-notification__dismiss"}],optOut:[{hide:".app-layout .app-cookies-notification"}]},{name:"Sirdata",cosmetic:!1,prehideSelectors:["#sd-cmp"],detectCmp:[{exists:"#sd-cmp"}],detectPopup:[{visible:"#sd-cmp"}],optIn:[{waitForThenClick:"#sd-cmp .sd-cmp-3cRQ2"}],optOut:[{waitForThenClick:["#sd-cmp","xpath///span[contains(., 'Do not accept') or contains(., 'Acceptera inte') or contains(., 'No aceptar') or contains(., 'Ikke acceptere') or contains(., 'Nicht akzeptieren') or contains(., 'Не приемам') or contains(., 'Να μην γίνει αποδοχή') or contains(., 'Niet accepteren') or contains(., 'Nepřijímat') or contains(., 'Nie akceptuj') or contains(., 'Nu acceptați') or contains(., 'Não aceitar') or contains(., 'Continuer sans accepter') or contains(., 'Non accettare') or contains(., 'Nem fogad el')]"]}]},{name:"snigel",detectCmp:[{exists:".snigel-cmp-framework"}],detectPopup:[{visible:".snigel-cmp-framework"}],optOut:[{click:"#sn-b-custom"},{click:"#sn-b-save"}],test:[{eval:"EVAL_SNIGEL_0"}],optIn:[{click:".snigel-cmp-framework #accept-choices"}]},{name:"steampowered.com",detectCmp:[{exists:".cookiepreferences_popup"},{visible:".cookiepreferences_popup"}],detectPopup:[{visible:".cookiepreferences_popup"}],optOut:[{click:"#rejectAllButton"}],optIn:[{click:"#acceptAllButton"}],test:[{wait:1e3},{eval:"EVAL_STEAMPOWERED_0"}]},{name:"strato.de",prehideSelectors:[".consent__wrapper"],runContext:{urlPattern:"^https://www\\.strato\\.de/"},detectCmp:[{exists:".consent"}],detectPopup:[{visible:".consent"}],optIn:[{click:"button.consentAgree"}],optOut:[{click:"button.consentSettings"},{waitForThenClick:"button#consentSubmit"}]},{name:"svt.se",vendorUrl:"https://www.svt.se/",runContext:{urlPattern:"^https://www\\.svt\\.se/"},prehideSelectors:["[class*=CookieConsent__root___]"],detectCmp:[{exists:"[class*=CookieConsent__root___]"}],detectPopup:[{visible:"[class*=CookieConsent__modal___]"}],optIn:[{waitForThenClick:"[class*=CookieConsent__modal___] > div > button[class*=primary]"}],optOut:[{waitForThenClick:"[class*=CookieConsent__modal___] > div > button[class*=secondary]:nth-child(2)"}],test:[{eval:"EVAL_SVT_TEST"}]},{name:"takealot.com",cosmetic:!0,prehideSelectors:['div[class^="cookies-banner-module_"]'],detectCmp:[{exists:'div[class^="cookies-banner-module_cookie-banner_"]'}],detectPopup:[{exists:'div[class^="cookies-banner-module_cookie-banner_"]'}],optIn:[{click:'button[class*="cookies-banner-module_dismiss-button_"]'}],optOut:[{hide:'div[class^="cookies-banner-module_"]'},{if:{exists:'div[class^="cookies-banner-module_small-cookie-banner_"]'},then:[{eval:"EVAL_TAKEALOT_0"}],else:[]}]},{name:"tarteaucitron.js",prehideSelectors:["#tarteaucitronRoot"],detectCmp:[{exists:"#tarteaucitronRoot"}],detectPopup:[{visible:"#tarteaucitronRoot #tarteaucitronAlertBig",check:"any"}],optIn:[{eval:"EVAL_TARTEAUCITRON_1"}],optOut:[{eval:"EVAL_TARTEAUCITRON_0"}],test:[{eval:"EVAL_TARTEAUCITRON_2",comment:"sometimes there are required categories, so we check that at least something is false"}]},{name:"taunton",vendorUrl:"https://www.taunton.com/",prehideSelectors:["#taunton-user-consent__overlay"],detectCmp:[{exists:"#taunton-user-consent__overlay"}],detectPopup:[{exists:"#taunton-user-consent__overlay:not([aria-hidden=true])"}],optIn:[{click:"#taunton-user-consent__toolbar input[type=checkbox]:not(:checked)"},{click:"#taunton-user-consent__toolbar button[type=submit]"}],optOut:[{click:"#taunton-user-consent__toolbar input[type=checkbox]:checked",optional:!0,all:!0},{click:"#taunton-user-consent__toolbar button[type=submit]"}],test:[{eval:"EVAL_TAUNTON_TEST"}]},{name:"Tealium",prehideSelectors:["#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs,#__tealiumImplicitmodal,#consent-layer"],detectCmp:[{exists:"#__tealiumGDPRecModal *,#__tealiumGDPRcpPrefs *,#__tealiumImplicitmodal *"},{eval:"EVAL_TEALIUM_0"}],detectPopup:[{visible:"#__tealiumGDPRecModal *,#__tealiumGDPRcpPrefs *,#__tealiumImplicitmodal *",check:"any"}],optOut:[{eval:"EVAL_TEALIUM_1"},{eval:"EVAL_TEALIUM_DONOTSELL"},{hide:"#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs,#__tealiumImplicitmodal"},{waitForThenClick:"#cm-acceptNone,.js-accept-essential-cookies",timeout:1e3,optional:!0}],optIn:[{hide:"#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs"},{eval:"EVAL_TEALIUM_2"}],test:[{eval:"EVAL_TEALIUM_3"},{eval:"EVAL_TEALIUM_DONOTSELL_CHECK"},{visible:"#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs",check:"none"}]},{name:"temu",vendorUrl:"https://temu.com",runContext:{urlPattern:"^https://[^/]*temu\\.com/"},prehideSelectors:["._2d-8vq-W,._1UdBUwni"],detectCmp:[{exists:"._3YCsmIaS"}],detectPopup:[{visible:"._3YCsmIaS"}],optIn:[{waitForThenClick:"._3fKiu5wx._3zN5SumS._3tAK973O.IYOfhWEs.VGNGF1pA"}],optOut:[{waitForThenClick:"._3fKiu5wx._1_XToJBF._3tAK973O.IYOfhWEs.VGNGF1pA"}]},{name:"Termly",prehideSelectors:["#termly-code-snippet-support"],detectCmp:[{exists:"#termly-code-snippet-support"}],detectPopup:[{visible:"#termly-code-snippet-support div"}],optIn:[{waitForThenClick:'[data-tid="banner-accept"]'}],optOut:[{if:{exists:'[data-tid="banner-decline"]'},then:[{click:'[data-tid="banner-decline"]'}],else:[{click:".t-preference-button"},{wait:500},{if:{exists:".t-declineAllButton"},then:[{click:".t-declineAllButton"}],else:[{waitForThenClick:".t-preference-modal input[type=checkbox][checked]:not([disabled])",all:!0},{waitForThenClick:".t-saveButton"}]}]}]},{name:"termsfeed",vendorUrl:"https://termsfeed.com",comment:"v4.x.x",prehideSelectors:[".termsfeed-com---nb"],detectCmp:[{exists:".termsfeed-com---nb"}],detectPopup:[{visible:".termsfeed-com---nb"}],optIn:[{waitForThenClick:".cc-nb-okagree"}],optOut:[{waitForThenClick:".cc-nb-reject"}]},{name:"termsfeed3",vendorUrl:"https://termsfeed.com",comment:"v3.x.x",prehideSelectors:[".cc_dialog.cc_css_reboot,.cc_overlay_lock"],detectCmp:[{exists:".cc_dialog.cc_css_reboot"}],detectPopup:[{visible:".cc_dialog.cc_css_reboot"}],optIn:[{waitForThenClick:".cc_dialog.cc_css_reboot .cc_b_ok"}],optOut:[{if:{exists:".cc_dialog.cc_css_reboot .cc_b_cp"},then:[{click:".cc_dialog.cc_css_reboot .cc_b_cp"},{waitForVisible:".cookie-consent-preferences-dialog .cc_cp_f_save button"},{waitForThenClick:".cookie-consent-preferences-dialog .cc_cp_f_save button"}],else:[{hide:".cc_dialog.cc_css_reboot,.cc_overlay_lock"}]}]},{name:"Test page cosmetic CMP",cosmetic:!0,prehideSelectors:["#privacy-test-page-cmp-test-prehide"],detectCmp:[{exists:"#privacy-test-page-cmp-test-banner"}],detectPopup:[{visible:"#privacy-test-page-cmp-test-banner"}],optIn:[{waitFor:"#accept-all"},{click:"#accept-all"}],optOut:[{hide:"#privacy-test-page-cmp-test-banner"}],test:[{wait:500},{eval:"EVAL_TESTCMP_COSMETIC_0"}]},{name:"Test page CMP",prehideSelectors:["#reject-all"],detectCmp:[{exists:"#privacy-test-page-cmp-test"}],detectPopup:[{visible:"#privacy-test-page-cmp-test"}],optIn:[{waitFor:"#accept-all"},{click:"#accept-all"}],optOut:[{waitFor:"#reject-all"},{click:"#reject-all"}],test:[{eval:"EVAL_TESTCMP_0"}]},{name:"thalia.de",prehideSelectors:[".consent-banner-box"],detectCmp:[{exists:"consent-banner[component=consent-banner]"}],detectPopup:[{visible:".consent-banner-box"}],optIn:[{click:".button-zustimmen"}],optOut:[{click:"button[data-consent=disagree]"}]},{name:"thefreedictionary.com",prehideSelectors:["#cmpBanner"],detectCmp:[{exists:"#cmpBanner"}],detectPopup:[{visible:"#cmpBanner"}],optIn:[{eval:"EVAL_THEFREEDICTIONARY_1"}],optOut:[{eval:"EVAL_THEFREEDICTIONARY_0"}]},{name:"theverge",runContext:{frame:!1,main:!0,urlPattern:"^https://(www)?\\.theverge\\.com"},intermediate:!1,prehideSelectors:[".duet--cta--cookie-banner"],detectCmp:[{exists:".duet--cta--cookie-banner"}],detectPopup:[{visible:".duet--cta--cookie-banner"}],optIn:[{click:".duet--cta--cookie-banner button.tracking-12",all:!1}],optOut:[{click:".duet--cta--cookie-banner button.tracking-12 > span"}],test:[{eval:"EVAL_THEVERGE_0"}]},{name:"tidbits-com",cosmetic:!0,prehideSelectors:["#eu_cookie_law_widget-2"],detectCmp:[{exists:"#eu_cookie_law_widget-2"}],detectPopup:[{visible:"#eu_cookie_law_widget-2"}],optIn:[{click:"#eu-cookie-law form > input.accept"}],optOut:[{hide:"#eu_cookie_law_widget-2"}]},{name:"tractor-supply",runContext:{urlPattern:"^https://www\\.tractorsupply\\.com/"},cosmetic:!0,prehideSelectors:[".tsc-cookie-banner"],detectCmp:[{exists:".tsc-cookie-banner"}],detectPopup:[{visible:".tsc-cookie-banner"}],optIn:[{click:"#cookie-banner-cancel"}],optOut:[{hide:".tsc-cookie-banner"}]},{name:"trader-joes-com",cosmetic:!0,prehideSelectors:['div.aem-page > div[class^="CookiesAlert_cookiesAlert__"]'],detectCmp:[{exists:'div.aem-page > div[class^="CookiesAlert_cookiesAlert__"]'}],detectPopup:[{visible:'div.aem-page > div[class^="CookiesAlert_cookiesAlert__"]'}],optIn:[{click:'div[class^="CookiesAlert_cookiesAlert__container__"] button'}],optOut:[{hide:'div.aem-page > div[class^="CookiesAlert_cookiesAlert__"]'}]},{name:"transcend",vendorUrl:"https://unknown",cosmetic:!0,prehideSelectors:["#transcend-consent-manager"],detectCmp:[{exists:"#transcend-consent-manager"}],detectPopup:[{visible:"#transcend-consent-manager"}],optIn:[{waitForThenClick:["#transcend-consent-manager","#consentManagerMainDialog .inner-container button"]}],optOut:[{hide:"#transcend-consent-manager"}]},{name:"transip-nl",runContext:{urlPattern:"^https://www\\.transip\\.nl/"},prehideSelectors:["#consent-modal"],detectCmp:[{any:[{exists:"#consent-modal"},{exists:"#privacy-settings-content"}]}],detectPopup:[{any:[{visible:"#consent-modal"},{visible:"#privacy-settings-content"}]}],optIn:[{click:'button[type="submit"]'}],optOut:[{if:{exists:"#privacy-settings-content"},then:[{click:'button[type="submit"]'}],else:[{click:"div.one-modal__action-footer-column--secondary > a"}]}]},{name:"tropicfeel-com",prehideSelectors:["#shopify-section-cookies-controller"],detectCmp:[{exists:"#shopify-section-cookies-controller"}],detectPopup:[{visible:"#shopify-section-cookies-controller #cookies-controller-main-pane",check:"any"}],optIn:[{waitForThenClick:"#cookies-controller-main-pane form[data-form-allow-all] button"}],optOut:[{click:"#cookies-controller-main-pane a[data-tab-target=manage-cookies]"},{waitFor:"#manage-cookies-pane.active"},{click:"#manage-cookies-pane.active input[type=checkbox][checked]:not([disabled])",all:!0},{click:"#manage-cookies-pane.active button[type=submit]"}],test:[]},{name:"true-car",runContext:{urlPattern:"^https://www\\.truecar\\.com/"},cosmetic:!0,prehideSelectors:[['div[aria-labelledby="cookie-banner-heading"]']],detectCmp:[{exists:'div[aria-labelledby="cookie-banner-heading"]'}],detectPopup:[{visible:'div[aria-labelledby="cookie-banner-heading"]'}],optIn:[{click:'div[aria-labelledby="cookie-banner-heading"] > button[aria-label="Close"]'}],optOut:[{hide:'div[aria-labelledby="cookie-banner-heading"]'}]},{name:"truyo",prehideSelectors:["#truyo-consent-module"],detectCmp:[{exists:"#truyo-cookieBarContent"}],detectPopup:[{visible:"#truyo-consent-module"}],optIn:[{click:"button#acceptAllCookieButton"}],optOut:[{click:"button#declineAllCookieButton"}]},{name:"twitch-mobile",vendorUrl:"https://m.twitch.tv/",cosmetic:!0,runContext:{urlPattern:"^https?://m\\.twitch\\.tv"},prehideSelectors:[],detectCmp:[{exists:'.ReactModal__Overlay [href="https://www.twitch.tv/p/cookie-policy"]'}],detectPopup:[{visible:'.ReactModal__Overlay [href="https://www.twitch.tv/p/cookie-policy"]'}],optIn:[{waitForThenClick:'.ReactModal__Overlay:has([href="https://www.twitch.tv/p/cookie-policy"]) button'}],optOut:[{hide:'.ReactModal__Overlay:has([href="https://www.twitch.tv/p/cookie-policy"])'}]},{name:"twitch.tv",runContext:{urlPattern:"^https?://(www\\.)?twitch\\.tv"},prehideSelectors:["div:has(> .consent-banner .consent-banner__content--gdpr-v2),.ReactModalPortal:has([data-a-target=consent-modal-save])"],detectCmp:[{exists:".consent-banner .consent-banner__content--gdpr-v2"}],detectPopup:[{visible:".consent-banner .consent-banner__content--gdpr-v2"}],optIn:[{click:'button[data-a-target="consent-banner-accept"]'}],optOut:[{hide:"div:has(> .consent-banner .consent-banner__content--gdpr-v2)"},{click:'button[data-a-target="consent-banner-manage-preferences"]'},{waitFor:"input[type=checkbox][data-a-target=tw-checkbox]"},{click:"input[type=checkbox][data-a-target=tw-checkbox][checked]:not([disabled])",all:!0,optional:!0},{waitForThenClick:"[data-a-target=consent-modal-save]"},{waitForVisible:".ReactModalPortal:has([data-a-target=consent-modal-save])",check:"none"}]},{name:"twitter",runContext:{urlPattern:"^https://([a-z0-9-]+\\.)?twitter\\.com/"},prehideSelectors:['[data-testid="BottomBar"]'],detectCmp:[{exists:'[data-testid="BottomBar"] div'}],detectPopup:[{visible:'[data-testid="BottomBar"] div'}],optIn:[{waitForThenClick:'[data-testid="BottomBar"] > div:has(>div:first-child>div:last-child>span[role=button]) > div:last-child > div[role=button]:first-child'}],optOut:[{waitForThenClick:'[data-testid="BottomBar"] > div:has(>div:first-child>div:last-child>span[role=button]) > div:last-child > div[role=button]:last-child'}],TODOtest:[{eval:"EVAL_document.cookie.includes('d_prefs=MjoxLGNvbnNlbnRfdmVyc2lvbjoy')"}]},{name:"ubuntu.com",prehideSelectors:["dialog.cookie-policy"],detectCmp:[{any:[{exists:"dialog.cookie-policy header"},{exists:'xpath///*[@id="modal"]/div/header'}]}],detectPopup:[{any:[{visible:"dialog header"},{visible:'xpath///*[@id="modal"]/div/header'}]}],optIn:[{any:[{waitForThenClick:"#cookie-policy-button-accept"},{waitForThenClick:'xpath///*[@id="cookie-policy-button-accept"]'}]}],optOut:[{any:[{waitForThenClick:"button.js-manage"},{waitForThenClick:'xpath///*[@id="cookie-policy-content"]/p[4]/button[2]'}]},{waitForThenClick:"dialog.cookie-policy .p-switch__input:checked",optional:!0,all:!0,timeout:500},{any:[{waitForThenClick:"dialog.cookie-policy .js-save-preferences"},{waitForThenClick:'xpath///*[@id="modal"]/div/button'}]}],test:[{eval:"EVAL_UBUNTU_COM_0"}]},{name:"UK Cookie Consent",prehideSelectors:["#catapult-cookie-bar"],cosmetic:!0,detectCmp:[{exists:"#catapult-cookie-bar"}],detectPopup:[{exists:".has-cookie-bar #catapult-cookie-bar"}],optIn:[{click:"#catapultCookie"}],optOut:[{hide:"#catapult-cookie-bar"}],test:[{eval:"EVAL_UK_COOKIE_CONSENT_0"}]},{name:"urbanarmorgear-com",cosmetic:!0,prehideSelectors:['div[class^="Layout__CookieBannerContainer-"]'],detectCmp:[{exists:'div[class^="Layout__CookieBannerContainer-"]'}],detectPopup:[{visible:'div[class^="Layout__CookieBannerContainer-"]'}],optIn:[{click:'button[class^="CookieBanner__AcceptButton"]'}],optOut:[{hide:'div[class^="Layout__CookieBannerContainer-"]'}]},{name:"usercentrics-api",detectCmp:[{exists:"#usercentrics-root"}],detectPopup:[{eval:"EVAL_USERCENTRICS_API_0"},{exists:["#usercentrics-root","[data-testid=uc-container]"]},{waitForVisible:"#usercentrics-root",timeout:2e3}],optIn:[{eval:"EVAL_USERCENTRICS_API_3"},{eval:"EVAL_USERCENTRICS_API_1"},{eval:"EVAL_USERCENTRICS_API_5"}],optOut:[{eval:"EVAL_USERCENTRICS_API_1"},{eval:"EVAL_USERCENTRICS_API_2"}],test:[{eval:"EVAL_USERCENTRICS_API_6"}]},{name:"usercentrics-button",detectCmp:[{exists:"#usercentrics-button"}],detectPopup:[{visible:"#usercentrics-button #uc-btn-accept-banner"}],optIn:[{click:"#usercentrics-button #uc-btn-accept-banner"}],optOut:[{click:"#usercentrics-button #uc-btn-deny-banner"}],test:[{eval:"EVAL_USERCENTRICS_BUTTON_0"}]},{name:"uswitch.com",runContext:{main:!0,frame:!1,urlPattern:"^https://(www\\.)?uswitch\\.com/"},prehideSelectors:[".ucb"],detectCmp:[{exists:".ucb-banner"}],detectPopup:[{visible:".ucb-banner"}],optIn:[{waitForThenClick:".ucb-banner .ucb-btn-accept"}],optOut:[{waitForThenClick:".ucb-banner .ucb-btn-save"}]},{name:"vodafone.de",runContext:{urlPattern:"^https://www\\.vodafone\\.de/"},prehideSelectors:[".dip-consent,.dip-consent-container"],detectCmp:[{exists:".dip-consent-container"}],detectPopup:[{visible:".dip-consent-content"}],optOut:[{click:'.dip-consent-btn[tabindex="2"]'}],optIn:[{click:'.dip-consent-btn[tabindex="1"]'}]},{name:"waitrose.com",prehideSelectors:["div[aria-labelledby=CookieAlertModalHeading]","section[data-test=initial-waitrose-cookie-consent-banner]","section[data-test=cookie-consent-modal]"],detectCmp:[{exists:"section[data-test=initial-waitrose-cookie-consent-banner]"}],detectPopup:[{visible:"section[data-test=initial-waitrose-cookie-consent-banner]"}],optIn:[{click:"button[data-test=accept-all]"}],optOut:[{click:"button[data-test=manage-cookies]"},{wait:200},{eval:"EVAL_WAITROSE_0"},{click:"button[data-test=submit]"}],test:[{eval:"EVAL_WAITROSE_1"}]},{name:"webflow",vendorUrl:"https://webflow.com/",prehideSelectors:[".fs-cc-components"],detectCmp:[{exists:".fs-cc-components"}],detectPopup:[{visible:".fs-cc-components"},{visible:"[fs-cc=banner]"}],optIn:[{wait:500},{waitForThenClick:"[fs-cc=banner] [fs-cc=allow]"}],optOut:[{wait:500},{waitForThenClick:"[fs-cc=banner] [fs-cc=deny]"}]},{name:"wetransfer.com",detectCmp:[{exists:".welcome__cookie-notice"}],detectPopup:[{visible:".welcome__cookie-notice"}],optIn:[{click:".welcome__button--accept"}],optOut:[{click:".welcome__button--decline"}]},{name:"whitepages.com",runContext:{urlPattern:"^https://www\\.whitepages\\.com/"},cosmetic:!0,prehideSelectors:[".cookie-wrapper, .cookie-overlay"],detectCmp:[{exists:".cookie-wrapper"}],detectPopup:[{visible:".cookie-overlay"}],optIn:[{click:'button[aria-label="Got it"]'}],optOut:[{hide:".cookie-wrapper"}]},{name:"wolframalpha",vendorUrl:"https://www.wolframalpha.com",prehideSelectors:[],cosmetic:!0,runContext:{urlPattern:"^https://www\\.wolframalpha\\.com/"},detectCmp:[{exists:"section._a_yb"}],detectPopup:[{visible:"section._a_yb"}],optIn:[{waitForThenClick:"section._a_yb button"}],optOut:[{hide:"section._a_yb"}]},{name:"woo-commerce-com",prehideSelectors:[".wccom-comp-privacy-banner .wccom-privacy-banner"],detectCmp:[{exists:".wccom-comp-privacy-banner .wccom-privacy-banner"}],detectPopup:[{exists:".wccom-comp-privacy-banner .wccom-privacy-banner"}],optIn:[{click:".wccom-privacy-banner__content-buttons button.is-primary"}],optOut:[{click:".wccom-privacy-banner__content-buttons button.is-secondary"},{waitForThenClick:"input[type=checkbox][checked]:not([disabled])",all:!0},{click:"div.wccom-modal__footer > button"}]},{name:"WP Cookie Notice for GDPR",vendorUrl:"https://wordpress.org/plugins/gdpr-cookie-consent/",prehideSelectors:["#gdpr-cookie-consent-bar"],detectCmp:[{exists:"#gdpr-cookie-consent-bar"}],detectPopup:[{visible:"#gdpr-cookie-consent-bar"}],optIn:[{waitForThenClick:"#gdpr-cookie-consent-bar #cookie_action_accept"}],optOut:[{waitForThenClick:"#gdpr-cookie-consent-bar #cookie_action_reject"}],test:[{eval:"EVAL_WP_COOKIE_NOTICE_0"}]},{name:"wpcc",cosmetic:!0,prehideSelectors:[".wpcc-container"],detectCmp:[{exists:".wpcc-container"}],detectPopup:[{exists:".wpcc-container .wpcc-message"}],optIn:[{click:".wpcc-compliance .wpcc-btn"}],optOut:[{hide:".wpcc-container"}]},{name:"xe.com",vendorUrl:"https://www.xe.com/",runContext:{urlPattern:"^https://www\\.xe\\.com/"},prehideSelectors:["[class*=ConsentBanner]"],detectCmp:[{exists:"[class*=ConsentBanner]"}],detectPopup:[{visible:"[class*=ConsentBanner]"}],optIn:[{waitForThenClick:"[class*=ConsentBanner] .egnScw"}],optOut:[{wait:1e3},{waitForThenClick:"[class*=ConsentBanner] .frDWEu"},{waitForThenClick:"[class*=ConsentBanner] .hXIpFU"}],test:[{eval:"EVAL_XE_TEST"}]},{name:"xhamster-eu",prehideSelectors:[".cookies-modal"],detectCmp:[{exists:".cookies-modal"}],detectPopup:[{exists:".cookies-modal"}],optIn:[{click:"button.cmd-button-accept-all"}],optOut:[{click:"button.cmd-button-reject-all"}]},{name:"xhamster-us",runContext:{urlPattern:"^https://(www\\.)?xhamster\\d?\\.com"},cosmetic:!0,prehideSelectors:[".cookie-announce"],detectCmp:[{exists:".cookie-announce"}],detectPopup:[{visible:".cookie-announce .announce-text"}],optIn:[{click:".cookie-announce button.xh-button"}],optOut:[{hide:".cookie-announce"}]},{name:"xing.com",detectCmp:[{exists:"div[class^=cookie-consent-CookieConsent]"}],detectPopup:[{exists:"div[class^=cookie-consent-CookieConsent]"}],optIn:[{click:"#consent-accept-button"}],optOut:[{click:"#consent-settings-button"},{click:".consent-banner-button-accept-overlay"}],test:[{eval:"EVAL_XING_0"}]},{name:"xnxx-com",cosmetic:!0,prehideSelectors:["#cookies-use-alert"],detectCmp:[{exists:"#cookies-use-alert"}],detectPopup:[{visible:"#cookies-use-alert"}],optIn:[{click:"#cookies-use-alert .close"}],optOut:[{hide:"#cookies-use-alert"}]},{name:"xvideos",vendorUrl:"https://xvideos.com",runContext:{urlPattern:"^https://[^/]*xvideos\\.com/"},prehideSelectors:[],detectCmp:[{exists:".disclaimer-opened #disclaimer-cookies"}],detectPopup:[{visible:".disclaimer-opened #disclaimer-cookies"}],optIn:[{waitForThenClick:"#disclaimer-accept_cookies"}],optOut:[{waitForThenClick:"#disclaimer-reject_cookies"}]},{name:"Yahoo",runContext:{urlPattern:"^https://consent\\.yahoo\\.com/v2/"},prehideSelectors:["#reject-all"],detectCmp:[{exists:"#consent-page"}],detectPopup:[{visible:"#consent-page"}],optIn:[{waitForThenClick:"#consent-page button[value=agree]"}],optOut:[{waitForThenClick:"#consent-page button[value=reject]"}]},{name:"youporn.com",cosmetic:!0,prehideSelectors:[".euCookieModal, #js_euCookieModal"],detectCmp:[{exists:".euCookieModal"}],detectPopup:[{exists:".euCookieModal, #js_euCookieModal"}],optIn:[{click:'button[name="user_acceptCookie"]'}],optOut:[{hide:".euCookieModal"}]},{name:"youtube-desktop",prehideSelectors:["tp-yt-iron-overlay-backdrop.opened","ytd-consent-bump-v2-lightbox"],detectCmp:[{exists:"ytd-consent-bump-v2-lightbox tp-yt-paper-dialog"},{exists:'ytd-consent-bump-v2-lightbox tp-yt-paper-dialog a[href^="https://consent.youtube.com/"]'}],detectPopup:[{visible:"ytd-consent-bump-v2-lightbox tp-yt-paper-dialog"}],optIn:[{waitForThenClick:"ytd-consent-bump-v2-lightbox .eom-buttons .eom-button-row:first-child ytd-button-renderer:last-child #button,ytd-consent-bump-v2-lightbox .eom-buttons .eom-button-row:first-child ytd-button-renderer:last-child button"},{wait:500}],optOut:[{waitForThenClick:"ytd-consent-bump-v2-lightbox .eom-buttons .eom-button-row:first-child ytd-button-renderer:first-child #button,ytd-consent-bump-v2-lightbox .eom-buttons .eom-button-row:first-child ytd-button-renderer:first-child button"},{wait:500}],test:[{wait:500},{eval:"EVAL_YOUTUBE_DESKTOP_0"}]},{name:"youtube-mobile",prehideSelectors:[".consent-bump-v2-lightbox"],detectCmp:[{exists:"ytm-consent-bump-v2-renderer"}],detectPopup:[{visible:"ytm-consent-bump-v2-renderer"}],optIn:[{waitForThenClick:"ytm-consent-bump-v2-renderer .privacy-terms + .one-col-dialog-buttons c3-material-button:first-child button, ytm-consent-bump-v2-renderer .privacy-terms + .one-col-dialog-buttons ytm-button-renderer:first-child button"},{wait:500}],optOut:[{waitForThenClick:"ytm-consent-bump-v2-renderer .privacy-terms + .one-col-dialog-buttons c3-material-button:nth-child(2) button, ytm-consent-bump-v2-renderer .privacy-terms + .one-col-dialog-buttons ytm-button-renderer:nth-child(2) button"},{wait:500}],test:[{wait:500},{eval:"EVAL_YOUTUBE_MOBILE_0"}]},{name:"zdf",prehideSelectors:["#zdf-cmp-banner-sdk"],detectCmp:[{exists:"#zdf-cmp-banner-sdk"}],detectPopup:[{visible:"#zdf-cmp-main.zdf-cmp-show"}],optIn:[{waitForThenClick:"#zdf-cmp-main #zdf-cmp-accept-btn"}],optOut:[{waitForThenClick:"#zdf-cmp-main #zdf-cmp-deny-btn"}],test:[]}],C={"didomi.io":{detectors:[{presentMatcher:{target:{selector:"#didomi-host, #didomi-notice"},type:"css"},showingMatcher:{target:{selector:"body.didomi-popup-open, .didomi-notice-banner"},type:"css"}}],methods:[{action:{target:{selector:".didomi-popup-notice-buttons .didomi-button:not(.didomi-button-highlight), .didomi-notice-banner .didomi-learn-more-button"},type:"click"},name:"OPEN_OPTIONS"},{action:{actions:[{retries:50,target:{selector:"#didomi-purpose-cookies"},type:"waitcss",waitTime:50},{consents:[{description:"Share (everything) with others",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-share_whith_others]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-share_whith_others]:last-child"},type:"click"},type:"X"},{description:"Information storage and access",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-cookies]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-cookies]:last-child"},type:"click"},type:"D"},{description:"Content selection, offers and marketing",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-CL-T1Rgm7]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-CL-T1Rgm7]:last-child"},type:"click"},type:"E"},{description:"Analytics",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-analytics]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-analytics]:last-child"},type:"click"},type:"B"},{description:"Analytics",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-M9NRHJe3G]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-M9NRHJe3G]:last-child"},type:"click"},type:"B"},{description:"Ad and content selection",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-advertising_personalization]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-advertising_personalization]:last-child"},type:"click"},type:"F"},{description:"Ad and content selection",falseAction:{parent:{childFilter:{target:{selector:"#didomi-purpose-pub-ciblee"}},selector:".didomi-consent-popup-data-processing, .didomi-components-accordion-label-container"},target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-pub-ciblee]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-pub-ciblee]:last-child"},type:"click"},type:"F"},{description:"Ad and content selection - basics",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-q4zlJqdcD]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-q4zlJqdcD]:last-child"},type:"click"},type:"F"},{description:"Ad and content selection - partners and subsidiaries",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-partenaire-cAsDe8jC]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-partenaire-cAsDe8jC]:last-child"},type:"click"},type:"F"},{description:"Ad and content selection - social networks",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-p4em9a8m]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-p4em9a8m]:last-child"},type:"click"},type:"F"},{description:"Ad and content selection - others",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-autres-pub]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-autres-pub]:last-child"},type:"click"},type:"F"},{description:"Social networks",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-reseauxsociaux]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-reseauxsociaux]:last-child"},type:"click"},type:"A"},{description:"Social networks",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-social_media]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-social_media]:last-child"},type:"click"},type:"A"},{description:"Content selection",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-content_personalization]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-content_personalization]:last-child"},type:"click"},type:"E"},{description:"Ad delivery",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-ad_delivery]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-ad_delivery]:last-child"},type:"click"},type:"F"}],type:"consent"},{action:{consents:[{matcher:{childFilter:{target:{selector:":not(.didomi-components-radio__option--selected)"}},type:"css"},trueAction:{target:{selector:":nth-child(2)"},type:"click"},falseAction:{target:{selector:":first-child"},type:"click"},type:"X"}],type:"consent"},target:{selector:".didomi-components-radio"},type:"foreach"}],type:"list"},name:"DO_CONSENT"},{action:{parent:{selector:".didomi-consent-popup-footer .didomi-consent-popup-actions"},target:{selector:".didomi-components-button:first-child"},type:"click"},name:"SAVE_CONSENT"}]},oil:{detectors:[{presentMatcher:{target:{selector:".as-oil-content-overlay"},type:"css"},showingMatcher:{target:{selector:".as-oil-content-overlay"},type:"css"}}],methods:[{action:{actions:[{target:{selector:".as-js-advanced-settings"},type:"click"},{retries:"10",target:{selector:".as-oil-cpc__purpose-container"},type:"waitcss",waitTime:"250"}],type:"list"},name:"OPEN_OPTIONS"},{action:{actions:[{consents:[{matcher:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Information storage and access","Opbevaring af og adgang til oplysninger på din enhed"]},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Information storage and access","Opbevaring af og adgang til oplysninger på din enhed"]},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"D"},{matcher:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Personlige annoncer","Personalisation"]},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Personlige annoncer","Personalisation"]},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"E"},{matcher:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Annoncevalg, levering og rapportering","Ad selection, delivery, reporting"]},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Annoncevalg, levering og rapportering","Ad selection, delivery, reporting"]},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"F"},{matcher:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Personalisering af indhold","Content selection, delivery, reporting"]},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Personalisering af indhold","Content selection, delivery, reporting"]},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"E"},{matcher:{parent:{childFilter:{target:{selector:".as-oil-cpc__purpose-header",textFilter:["Måling","Measurement"]}},selector:".as-oil-cpc__purpose-container"},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{childFilter:{target:{selector:".as-oil-cpc__purpose-header",textFilter:["Måling","Measurement"]}},selector:".as-oil-cpc__purpose-container"},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"B"},{matcher:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:"Google"},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:"Google"},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"F"}],type:"consent"}],type:"list"},name:"DO_CONSENT"},{action:{target:{selector:".as-oil__btn-optin"},type:"click"},name:"SAVE_CONSENT"},{action:{target:{selector:"div.as-oil"},type:"hide"},name:"HIDE_CMP"}]},optanon:{detectors:[{presentMatcher:{target:{selector:"#optanon-menu, .optanon-alert-box-wrapper"},type:"css"},showingMatcher:{target:{displayFilter:!0,selector:".optanon-alert-box-wrapper"},type:"css"}}],methods:[{action:{actions:[{target:{selector:".optanon-alert-box-wrapper .optanon-toggle-display, a[onclick*='OneTrust.ToggleInfoDisplay()'], a[onclick*='Optanon.ToggleInfoDisplay()']"},type:"click"}],type:"list"},name:"OPEN_OPTIONS"},{action:{actions:[{target:{selector:".preference-menu-item #Your-privacy"},type:"click"},{target:{selector:"#optanon-vendor-consent-text"},type:"click"},{action:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"X"}],type:"consent"},target:{selector:"#optanon-vendor-consent-list .vendor-item"},type:"foreach"},{target:{selector:".vendor-consent-back-link"},type:"click"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-performance"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-performance"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-functional"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-functional"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"E"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-advertising"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-advertising"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-social"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-social"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Social Media Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Social Media Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Personalisation"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Personalisation"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"E"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Site monitoring cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Site monitoring cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Third party privacy-enhanced content"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Third party privacy-enhanced content"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"X"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Performance & Advertising Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Performance & Advertising Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Information storage and access"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Information storage and access"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"D"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Ad selection, delivery, reporting"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Ad selection, delivery, reporting"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Content selection, delivery, reporting"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Content selection, delivery, reporting"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"E"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Measurement"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Measurement"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Recommended Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Recommended Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"X"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Unclassified Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Unclassified Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"X"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Analytical Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Analytical Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Marketing Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Marketing Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Personalization"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Personalization"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"E"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Ad Selection, Delivery & Reporting"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Ad Selection, Delivery & Reporting"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Content Selection, Delivery & Reporting"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Content Selection, Delivery & Reporting"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"E"}],type:"consent"}],type:"list"},type:"ifcss"}],type:"list"},name:"DO_CONSENT"},{action:{parent:{selector:".optanon-save-settings-button"},target:{selector:".optanon-white-button-middle"},type:"click"},name:"SAVE_CONSENT"},{action:{actions:[{target:{selector:"#optanon-popup-wrapper"},type:"hide"},{target:{selector:"#optanon-popup-bg"},type:"hide"},{target:{selector:".optanon-alert-box-wrapper"},type:"hide"}],type:"list"},name:"HIDE_CMP"}]},quantcast2:{detectors:[{presentMatcher:{target:{selector:"[data-tracking-opt-in-overlay]"},type:"css"},showingMatcher:{target:{selector:"[data-tracking-opt-in-overlay] [data-tracking-opt-in-learn-more]"},type:"css"}}],methods:[{action:{target:{selector:"[data-tracking-opt-in-overlay] [data-tracking-opt-in-learn-more]"},type:"click"},name:"OPEN_OPTIONS"},{action:{actions:[{type:"wait",waitTime:500},{action:{actions:[{target:{selector:"div",textFilter:["Information storage and access"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"D"}],type:"consent"},type:"ifcss"},{target:{selector:"div",textFilter:["Personalization"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"F"}],type:"consent"},type:"ifcss"},{target:{selector:"div",textFilter:["Ad selection, delivery, reporting"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"F"}],type:"consent"},type:"ifcss"},{target:{selector:"div",textFilter:["Content selection, delivery, reporting"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"E"}],type:"consent"},type:"ifcss"},{target:{selector:"div",textFilter:["Measurement"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"B"}],type:"consent"},type:"ifcss"},{target:{selector:"div",textFilter:["Other Partners"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"X"}],type:"consent"},type:"ifcss"}],type:"list"},parent:{childFilter:{target:{selector:"input"}},selector:"[data-tracking-opt-in-overlay] > div > div"},target:{childFilter:{target:{selector:"input"}},selector:":scope > div"},type:"foreach"}],type:"list"},name:"DO_CONSENT"},{action:{target:{selector:"[data-tracking-opt-in-overlay] [data-tracking-opt-in-save]"},type:"click"},name:"SAVE_CONSENT"}]},springer:{detectors:[{presentMatcher:{parent:null,target:{selector:".cmp-app_gdpr"},type:"css"},showingMatcher:{parent:null,target:{displayFilter:!0,selector:".cmp-popup_popup"},type:"css"}}],methods:[{action:{actions:[{target:{selector:".cmp-intro_rejectAll"},type:"click"},{type:"wait",waitTime:250},{target:{selector:".cmp-purposes_purposeItem:not(.cmp-purposes_selectedPurpose)"},type:"click"}],type:"list"},name:"OPEN_OPTIONS"},{action:{consents:[{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Przechowywanie informacji na urządzeniu lub dostęp do nich",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Przechowywanie informacji na urządzeniu lub dostęp do nich",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"D"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór podstawowych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór podstawowych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"F"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Tworzenie profilu spersonalizowanych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Tworzenie profilu spersonalizowanych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"F"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór spersonalizowanych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór spersonalizowanych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"E"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Tworzenie profilu spersonalizowanych treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Tworzenie profilu spersonalizowanych treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"E"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór spersonalizowanych treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór spersonalizowanych treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"B"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Pomiar wydajności reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Pomiar wydajności reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"B"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Pomiar wydajności treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Pomiar wydajności treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"B"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Stosowanie badań rynkowych w celu generowania opinii odbiorców",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Stosowanie badań rynkowych w celu generowania opinii odbiorców",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"X"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Opracowywanie i ulepszanie produktów",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Opracowywanie i ulepszanie produktów",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"X"}],type:"consent"},name:"DO_CONSENT"},{action:{target:{selector:".cmp-details_save"},type:"click"},name:"SAVE_CONSENT"}]},wordpressgdpr:{detectors:[{presentMatcher:{parent:null,target:{selector:".wpgdprc-consent-bar"},type:"css"},showingMatcher:{parent:null,target:{displayFilter:!0,selector:".wpgdprc-consent-bar"},type:"css"}}],methods:[{action:{parent:null,target:{selector:".wpgdprc-consent-bar .wpgdprc-consent-bar__settings",textFilter:null},type:"click"},name:"OPEN_OPTIONS"},{action:{actions:[{target:{selector:".wpgdprc-consent-modal .wpgdprc-button",textFilter:"Eyeota"},type:"click"},{consents:[{description:"Eyeota Cookies",matcher:{parent:{selector:".wpgdprc-consent-modal__description",textFilter:"Eyeota"},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".wpgdprc-consent-modal__description",textFilter:"Eyeota"},target:{selector:"label"},type:"click"},type:"X"}],type:"consent"},{target:{selector:".wpgdprc-consent-modal .wpgdprc-button",textFilter:"Advertising"},type:"click"},{consents:[{description:"Advertising Cookies",matcher:{parent:{selector:".wpgdprc-consent-modal__description",textFilter:"Advertising"},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".wpgdprc-consent-modal__description",textFilter:"Advertising"},target:{selector:"label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},name:"DO_CONSENT"},{action:{parent:null,target:{selector:".wpgdprc-button",textFilter:"Save my settings"},type:"click"},name:"SAVE_CONSENT"}]}},v={autoconsent:w,consentomatic:C},f=Object.freeze({__proto__:null,autoconsent:w,consentomatic:C,default:v});const A=new class{constructor(e,t=null,o=null){if(this.id=n(),this.rules=[],this.foundCmp=null,this.state={lifecycle:"loading",prehideOn:!1,findCmpAttempts:0,detectedCmps:[],detectedPopups:[],selfTest:null},a.sendContentMessage=e,this.sendContentMessage=e,this.rules=[],this.updateState({lifecycle:"loading"}),this.addDynamicRules(),t)this.initialize(t,o);else{o&&this.parseDeclarativeRules(o);e({type:"init",url:window.location.href}),this.updateState({lifecycle:"waitingForInitResponse"})}this.domActions=new class{constructor(e){this.autoconsentInstance=e}click(e,t=!1){const o=this.elementSelector(e);return this.autoconsentInstance.config.logs.rulesteps&&console.log("[click]",e,t,o),o.length>0&&(t?o.forEach((e=>e.click())):o[0].click()),o.length>0}elementExists(e){return this.elementSelector(e).length>0}elementVisible(e,t){const o=this.elementSelector(e),c=new Array(o.length);return o.forEach(((e,t)=>{c[t]=k(e)})),"none"===t?c.every((e=>!e)):0!==c.length&&("any"===t?c.some((e=>e)):c.every((e=>e)))}waitForElement(e,t=1e4){const o=Math.ceil(t/200);return this.autoconsentInstance.config.logs.rulesteps&&console.log("[waitForElement]",e),h((()=>this.elementSelector(e).length>0),o,200)}waitForVisible(e,t=1e4,o="any"){return h((()=>this.elementVisible(e,o)),Math.ceil(t/200),200)}async waitForThenClick(e,t=1e4,o=!1){return await this.waitForElement(e,t),this.click(e,o)}wait(e){return new Promise((t=>{setTimeout((()=>{t(!0)}),e)}))}hide(e,t){return m(u(),e,t)}prehide(e){const t=u("autoconsent-prehide");return this.autoconsentInstance.config.logs.lifecycle&&console.log("[prehide]",t,location.href),m(t,e,"opacity")}undoPrehide(){const e=u("autoconsent-prehide");return this.autoconsentInstance.config.logs.lifecycle&&console.log("[undoprehide]",e,location.href),e&&e.remove(),!!e}querySingleReplySelector(e,t=document){if(e.startsWith("aria/"))return[];if(e.startsWith("xpath/")){const o=e.slice(6),c=document.evaluate(o,t,null,XPathResult.ANY_TYPE,null);let i=null;const n=[];for(;i=c.iterateNext();)n.push(i);return n}return e.startsWith("text/")||e.startsWith("pierce/")?[]:t.shadowRoot?Array.from(t.shadowRoot.querySelectorAll(e)):Array.from(t.querySelectorAll(e))}querySelectorChain(e){let t,o=document;for(const c of e){if(t=this.querySingleReplySelector(c,o),0===t.length)return[];o=t[0]}return t}elementSelector(e){return"string"==typeof e?this.querySingleReplySelector(e):this.querySelectorChain(e)}}(this)}initialize(e,t){const o=b(e);if(o.logs.lifecycle&&console.log("autoconsent init",window.location.href),this.config=o,o.enabled){if(t&&this.parseDeclarativeRules(t),this.rules=function(e,t){return e.filter((e=>(!t.disabledCmps||!t.disabledCmps.includes(e.name))&&(t.enableCosmeticRules||!e.isCosmetic)))}(this.rules,o),e.enablePrehide)if(document.documentElement)this.prehideElements();else{const e=()=>{window.removeEventListener("DOMContentLoaded",e),this.prehideElements()};window.addEventListener("DOMContentLoaded",e)}if("loading"===document.readyState){const e=()=>{window.removeEventListener("DOMContentLoaded",e),this.start()};window.addEventListener("DOMContentLoaded",e)}else this.start();this.updateState({lifecycle:"initialized"})}else o.logs.lifecycle&&console.log("autoconsent is disabled")}addDynamicRules(){y.forEach((e=>{this.rules.push(new e(this))}))}parseDeclarativeRules(e){Object.keys(e.consentomatic).forEach((t=>{this.addConsentomaticCMP(t,e.consentomatic[t])})),e.autoconsent.forEach((e=>{this.addDeclarativeCMP(e)}))}addDeclarativeCMP(e){this.rules.push(new d(e,this))}addConsentomaticCMP(e,t){this.rules.push(new class{constructor(e,t){this.name=e,this.config=t,this.methods=new Map,this.runContext=l,this.isCosmetic=!1,t.methods.forEach((e=>{e.action&&this.methods.set(e.name,e.action)})),this.hasSelfTest=!1}get isIntermediate(){return!1}checkRunContext(){return!0}async detectCmp(){return this.config.detectors.map((e=>o(e.presentMatcher))).some((e=>!!e))}async detectPopup(){return this.config.detectors.map((e=>o(e.showingMatcher))).some((e=>!!e))}async executeAction(e,t){return!this.methods.has(e)||c(this.methods.get(e),t)}async optOut(){return await this.executeAction("HIDE_CMP"),await this.executeAction("OPEN_OPTIONS"),await this.executeAction("HIDE_CMP"),await this.executeAction("DO_CONSENT",[]),await this.executeAction("SAVE_CONSENT"),!0}async optIn(){return await this.executeAction("HIDE_CMP"),await this.executeAction("OPEN_OPTIONS"),await this.executeAction("HIDE_CMP"),await this.executeAction("DO_CONSENT",["D","A","B","E","F","X"]),await this.executeAction("SAVE_CONSENT"),!0}async openCmp(){return await this.executeAction("HIDE_CMP"),await this.executeAction("OPEN_OPTIONS"),!0}async test(){return!0}}(`com_${e}`,t))}start(){window.requestIdleCallback?window.requestIdleCallback((()=>this._start()),{timeout:500}):this._start()}async _start(){const e=this.config.logs;e.lifecycle&&console.log(`Detecting CMPs on ${window.location.href}`),this.updateState({lifecycle:"started"});const t=await this.findCmp(this.config.detectRetries);if(this.updateState({detectedCmps:t.map((e=>e.name))}),0===t.length)return e.lifecycle&&console.log("no CMP found",location.href),this.config.enablePrehide&&this.undoPrehide(),this.updateState({lifecycle:"nothingDetected"}),!1;this.updateState({lifecycle:"cmpDetected"});const o=[],c=[];for(const e of t)e.isCosmetic?c.push(e):o.push(e);let i=!1,n=await this.detectPopups(o,(async e=>{i=await this.handlePopup(e)}));if(0===n.length&&(n=await this.detectPopups(c,(async e=>{i=await this.handlePopup(e)}))),0===n.length)return e.lifecycle&&console.log("no popup found"),this.config.enablePrehide&&this.undoPrehide(),!1;if(n.length>1){const t={msg:"Found multiple CMPs, check the detection rules.",cmps:n.map((e=>e.name))};e.errors&&console.warn(t.msg,t.cmps),this.sendContentMessage({type:"autoconsentError",details:t})}return i}async findCmp(e){const t=this.config.logs;this.updateState({findCmpAttempts:this.state.findCmpAttempts+1});const o=[];for(const e of this.rules)try{if(!e.checkRunContext())continue;await e.detectCmp()&&(t.lifecycle&&console.log(`Found CMP: ${e.name} ${window.location.href}`),this.sendContentMessage({type:"cmpDetected",url:location.href,cmp:e.name}),o.push(e))}catch(o){t.errors&&console.warn(`error detecting ${e.name}`,o)}return 0===o.length&&e>0?(await this.domActions.wait(500),this.findCmp(e-1)):o}async detectPopup(e){if(await this.waitForPopup(e).catch((t=>(this.config.logs.errors&&console.warn(`error waiting for a popup for ${e.name}`,t),!1))))return this.updateState({detectedPopups:this.state.detectedPopups.concat([e.name])}),this.sendContentMessage({type:"popupFound",cmp:e.name,url:location.href}),e;throw new Error("Popup is not shown")}async detectPopups(e,t){const o=e.map((e=>this.detectPopup(e)));await Promise.any(o).then((e=>{t(e)})).catch((()=>null));const c=await Promise.allSettled(o),i=[];for(const e of c)"fulfilled"===e.status&&i.push(e.value);return i}async handlePopup(e){return this.updateState({lifecycle:"openPopupDetected"}),this.config.enablePrehide&&!this.state.prehideOn&&this.prehideElements(),this.foundCmp=e,"optOut"===this.config.autoAction?await this.doOptOut():"optIn"===this.config.autoAction?await this.doOptIn():(this.config.logs.lifecycle&&console.log("waiting for opt-out signal...",location.href),!0)}async doOptOut(){const e=this.config.logs;let t;return this.updateState({lifecycle:"runningOptOut"}),this.foundCmp?(e.lifecycle&&console.log(`CMP ${this.foundCmp.name}: opt out on ${window.location.href}`),t=await this.foundCmp.optOut(),e.lifecycle&&console.log(`${this.foundCmp.name}: opt out result ${t}`)):(e.errors&&console.log("no CMP to opt out"),t=!1),this.config.enablePrehide&&this.undoPrehide(),this.sendContentMessage({type:"optOutResult",cmp:this.foundCmp?this.foundCmp.name:"none",result:t,scheduleSelfTest:this.foundCmp&&this.foundCmp.hasSelfTest,url:location.href}),t&&!this.foundCmp.isIntermediate?(this.sendContentMessage({type:"autoconsentDone",cmp:this.foundCmp.name,isCosmetic:this.foundCmp.isCosmetic,url:location.href}),this.updateState({lifecycle:"done"})):this.updateState({lifecycle:t?"optOutSucceeded":"optOutFailed"}),t}async doOptIn(){const e=this.config.logs;let t;return this.updateState({lifecycle:"runningOptIn"}),this.foundCmp?(e.lifecycle&&console.log(`CMP ${this.foundCmp.name}: opt in on ${window.location.href}`),t=await this.foundCmp.optIn(),e.lifecycle&&console.log(`${this.foundCmp.name}: opt in result ${t}`)):(e.errors&&console.log("no CMP to opt in"),t=!1),this.config.enablePrehide&&this.undoPrehide(),this.sendContentMessage({type:"optInResult",cmp:this.foundCmp?this.foundCmp.name:"none",result:t,scheduleSelfTest:!1,url:location.href}),t&&!this.foundCmp.isIntermediate?(this.sendContentMessage({type:"autoconsentDone",cmp:this.foundCmp.name,isCosmetic:this.foundCmp.isCosmetic,url:location.href}),this.updateState({lifecycle:"done"})):this.updateState({lifecycle:t?"optInSucceeded":"optInFailed"}),t}async doSelfTest(){const e=this.config.logs;let t;return this.foundCmp?(e.lifecycle&&console.log(`CMP ${this.foundCmp.name}: self-test on ${window.location.href}`),t=await this.foundCmp.test()):(e.errors&&console.log("no CMP to self test"),t=!1),this.sendContentMessage({type:"selfTestResult",cmp:this.foundCmp?this.foundCmp.name:"none",result:t,url:location.href}),this.updateState({selfTest:t}),t}async waitForPopup(e,t=5,o=500){const c=this.config.logs;c.lifecycle&&console.log("checking if popup is open...",e.name);const i=await e.detectPopup().catch((t=>(c.errors&&console.warn(`error detecting popup for ${e.name}`,t),!1)));return!i&&t>0?(await this.domActions.wait(o),this.waitForPopup(e,t-1,o)):(c.lifecycle&&console.log(e.name,"popup is "+(i?"open":"not open")),i)}prehideElements(){const e=this.config.logs,t=this.rules.filter((e=>e.prehideSelectors&&e.checkRunContext())).reduce(((e,t)=>[...e,...t.prehideSelectors]),["#didomi-popup,.didomi-popup-container,.didomi-popup-notice,.didomi-consent-popup-preferences,#didomi-notice,.didomi-popup-backdrop,.didomi-screen-medium"]);return this.updateState({prehideOn:!0}),setTimeout((()=>{this.config.enablePrehide&&this.state.prehideOn&&!["runningOptOut","runningOptIn"].includes(this.state.lifecycle)&&(e.lifecycle&&console.log("Process is taking too long, unhiding elements"),this.undoPrehide())}),this.config.prehideTimeout||2e3),this.domActions.prehide(t.join(","))}undoPrehide(){return this.updateState({prehideOn:!1}),this.domActions.undoPrehide()}updateState(e){Object.assign(this.state,e),this.sendContentMessage({type:"report",instanceId:this.id,url:window.location.href,mainFrame:window.top===window.self,state:this.state})}async receiveMessageCallback(e){const t=this.config?.logs;switch(t?.messages&&console.log("received from background",e,window.location.href),e.type){case"initResp":this.initialize(e.config,e.rules);break;case"optIn":await this.doOptIn();break;case"optOut":await this.doOptOut();break;case"selfTest":await this.doSelfTest();break;case"evalResp":!function(e,t){const o=a.pending.get(e);o?(a.pending.delete(e),o.timer&&window.clearTimeout(o.timer),o.resolve(t)):console.warn("no eval #",e)}(e.id,e.result)}}}((e=>{window.webkit.messageHandlers[e.type]&&window.webkit.messageHandlers[e.type].postMessage(e).then((e=>{A.receiveMessageCallback(e)}))}),null,f);window.autoconsentMessageCallback=e=>{A.receiveMessageCallback(e)}}(); +!function(){"use strict";var e=class e{static setBase(t){e.base=t}static findElement(t,o=null,c=!1){let i=null;return i=null!=o?Array.from(o.querySelectorAll(t.selector)):null!=e.base?Array.from(e.base.querySelectorAll(t.selector)):Array.from(document.querySelectorAll(t.selector)),null!=t.textFilter&&(i=i.filter((e=>{const o=e.textContent.toLowerCase();if(Array.isArray(t.textFilter)){let e=!1;for(const c of t.textFilter)if(-1!==o.indexOf(c.toLowerCase())){e=!0;break}return e}if(null!=t.textFilter)return-1!==o.indexOf(t.textFilter.toLowerCase())}))),null!=t.styleFilters&&(i=i.filter((e=>{const o=window.getComputedStyle(e);let c=!0;for(const e of t.styleFilters){const t=o[e.option];c=e.negated?c&&t!==e.value:c&&t===e.value}return c}))),null!=t.displayFilter&&(i=i.filter((e=>t.displayFilter?0!==e.offsetHeight:0===e.offsetHeight))),null!=t.iframeFilter&&(i=i.filter((()=>t.iframeFilter?window.location!==window.parent.location:window.location===window.parent.location))),null!=t.childFilter&&(i=i.filter((o=>{const c=e.base;e.setBase(o);const i=e.find(t.childFilter);return e.setBase(c),null!=i.target}))),c?i:(i.length>1&&console.warn("Multiple possible targets: ",i,t,o),i[0])}static find(t,o=!1){const c=[];if(null!=t.parent){const i=e.findElement(t.parent,null,o);if(null!=i){if(i instanceof Array)return i.forEach((i=>{const n=e.findElement(t.target,i,o);n instanceof Array?n.forEach((e=>{c.push({parent:i,target:e})})):c.push({parent:i,target:n})})),c;{const n=e.findElement(t.target,i,o);n instanceof Array?n.forEach((e=>{c.push({parent:i,target:e})})):c.push({parent:i,target:n})}}}else{const i=e.findElement(t.target,null,o);i instanceof Array?i.forEach((e=>{c.push({parent:null,target:e})})):c.push({parent:null,target:i})}return 0===c.length&&c.push({parent:null,target:null}),o?c:(1!==c.length&&console.warn("Multiple results found, even though multiple false",c),c[0])}};e.base=null;var t=e;function o(e){const o=t.find(e);return"css"===e.type?!!o.target:"checkbox"===e.type?!!o.target&&o.target.checked:void 0}async function c(e,n){switch(e.type){case"click":return async function(e){const o=t.find(e);null!=o.target&&o.target.click();return i(0)}(e);case"list":return async function(e,t){for(const o of e.actions)await c(o,t)}(e,n);case"consent":return async function(e,t){for(const i of e.consents){const e=-1!==t.indexOf(i.type);if(i.matcher&&i.toggleAction){o(i.matcher)!==e&&await c(i.toggleAction)}else e?await c(i.trueAction):await c(i.falseAction)}}(e,n);case"ifcss":return async function(e,o){const i=t.find(e);i.target?e.falseAction&&await c(e.falseAction,o):e.trueAction&&await c(e.trueAction,o)}(e,n);case"waitcss":return async function(e){await new Promise((o=>{let c=e.retries||10;const i=e.waitTime||250,n=()=>{const a=t.find(e);(e.negated&&a.target||!e.negated&&!a.target)&&c>0?(c-=1,setTimeout(n,i)):o()};n()}))}(e);case"foreach":return async function(e,o){const i=t.find(e,!0),n=t.base;for(const n of i)n.target&&(t.setBase(n.target),await c(e.action,o));t.setBase(n)}(e,n);case"hide":return async function(e){const o=t.find(e);o.target&&o.target.classList.add("Autoconsent-Hidden")}(e);case"slide":return async function(e){const o=t.find(e),c=t.find(e.dragTarget);if(o.target){const e=o.target.getBoundingClientRect(),t=c.target.getBoundingClientRect();let i=t.top-e.top,n=t.left-e.left;"y"===this.config.axis.toLowerCase()&&(n=0),"x"===this.config.axis.toLowerCase()&&(i=0);const a=window.screenX+e.left+e.width/2,s=window.screenY+e.top+e.height/2,r=e.left+e.width/2,l=e.top+e.height/2,p=document.createEvent("MouseEvents");p.initMouseEvent("mousedown",!0,!0,window,0,a,s,r,l,!1,!1,!1,!1,0,o.target);const d=document.createEvent("MouseEvents");d.initMouseEvent("mousemove",!0,!0,window,0,a+n,s+i,r+n,l+i,!1,!1,!1,!1,0,o.target);const u=document.createEvent("MouseEvents");u.initMouseEvent("mouseup",!0,!0,window,0,a+n,s+i,r+n,l+i,!1,!1,!1,!1,0,o.target),o.target.dispatchEvent(p),await this.waitTimeout(10),o.target.dispatchEvent(d),await this.waitTimeout(10),o.target.dispatchEvent(u)}}(e);case"close":return async function(){window.close()}();case"wait":return async function(e){await i(e.waitTime)}(e);case"eval":return async function(e){return console.log("eval!",e.code),new Promise((t=>{try{e.async?(window.eval(e.code),setTimeout((()=>{t(window.eval("window.__consentCheckResult"))}),e.timeout||250)):t(window.eval(e.code))}catch(o){console.warn("eval error",o,e.code),t(!1)}}))}(e);default:throw"Unknown action type: "+e.type}}function i(e){return new Promise((t=>{setTimeout((()=>{t()}),e)}))}function n(){return crypto&&void 0!==crypto.randomUUID?crypto.randomUUID():Math.random().toString()}var a={pending:new Map,sendContentMessage:null};function s(e,t){const o=n();a.sendContentMessage({type:"eval",id:o,code:e,snippetId:t});const c=new class{constructor(e,t=1e3){this.id=e,this.promise=new Promise(((e,t)=>{this.resolve=e,this.reject=t})),this.timer=window.setTimeout((()=>{this.reject(new Error("timeout"))}),t)}}(o);return a.pending.set(c.id,c),c.promise}var r={EVAL_0:()=>console.log(1),EVAL_CONSENTMANAGER_1:()=>window.__cmp&&"object"==typeof __cmp("getCMPData"),EVAL_CONSENTMANAGER_2:()=>!__cmp("consentStatus").userChoiceExists,EVAL_CONSENTMANAGER_3:()=>__cmp("setConsent",0),EVAL_CONSENTMANAGER_4:()=>__cmp("setConsent",1),EVAL_CONSENTMANAGER_5:()=>__cmp("consentStatus").userChoiceExists,EVAL_COOKIEBOT_1:()=>!!window.Cookiebot,EVAL_COOKIEBOT_2:()=>!window.Cookiebot.hasResponse&&!0===window.Cookiebot.dialog?.visible,EVAL_COOKIEBOT_3:()=>window.Cookiebot.withdraw()||!0,EVAL_COOKIEBOT_4:()=>window.Cookiebot.hide()||!0,EVAL_COOKIEBOT_5:()=>!0===window.Cookiebot.declined,EVAL_KLARO_1:()=>{const e=globalThis.klaroConfig||globalThis.klaro?.getManager&&globalThis.klaro.getManager().config;if(!e)return!0;const t=(e.services||e.apps).filter((e=>!e.required)).map((e=>e.name));if(klaro&&klaro.getManager){const e=klaro.getManager();return t.every((t=>!e.consents[t]))}if(klaroConfig&&"cookie"===klaroConfig.storageMethod){const e=klaroConfig.cookieName||klaroConfig.storageName,o=JSON.parse(decodeURIComponent(document.cookie.split(";").find((t=>t.trim().startsWith(e))).split("=")[1]));return Object.keys(o).filter((e=>t.includes(e))).every((e=>!1===o[e]))}},EVAL_KLARO_OPEN_POPUP:()=>{klaro.show(void 0,!0)},EVAL_KLARO_TRY_API_OPT_OUT:()=>{if(window.klaro&&"function"==typeof klaro.show&&"function"==typeof klaro.getManager)try{return klaro.getManager().changeAll(!1),klaro.getManager().saveAndApplyConsents(),!0}catch(e){return console.warn(e),!1}return!1},EVAL_ONETRUST_1:()=>window.OnetrustActiveGroups.split(",").filter((e=>e.length>0)).length<=1,EVAL_TRUSTARC_TOP:()=>window&&window.truste&&"0"===window.truste.eu.bindMap.prefCookie,EVAL_TRUSTARC_FRAME_TEST:()=>window&&window.QueryString&&"0"===window.QueryString.preferences,EVAL_TRUSTARC_FRAME_GTM:()=>window&&window.QueryString&&"1"===window.QueryString.gtm,EVAL_ADROLL_0:()=>!document.cookie.includes("__adroll_fpc"),EVAL_ALMACMP_0:()=>document.cookie.includes('"name":"Google","consent":false'),EVAL_AFFINITY_SERIF_COM_0:()=>document.cookie.includes("serif_manage_cookies_viewed")&&!document.cookie.includes("serif_allow_analytics"),EVAL_ARBEITSAGENTUR_TEST:()=>document.cookie.includes("cookie_consent=denied"),EVAL_AXEPTIO_0:()=>document.cookie.includes("axeptio_authorized_vendors=%2C%2C"),EVAL_BAHN_TEST:()=>1===utag.gdpr.getSelectedCategories().length,EVAL_BING_0:()=>document.cookie.includes("AL=0")&&document.cookie.includes("AD=0")&&document.cookie.includes("SM=0"),EVAL_BLOCKSY_0:()=>document.cookie.includes("blocksy_cookies_consent_accepted=no"),EVAL_BORLABS_0:()=>!JSON.parse(decodeURIComponent(document.cookie.split(";").find((e=>-1!==e.indexOf("borlabs-cookie"))).split("=",2)[1])).consents.statistics,EVAL_BUNDESREGIERUNG_DE_0:()=>document.cookie.match("cookie-allow-tracking=0"),EVAL_CANVA_0:()=>!document.cookie.includes("gtm_fpc_engagement_event"),EVAL_CC_BANNER2_0:()=>!!document.cookie.match(/sncc=[^;]+D%3Dtrue/),EVAL_CLICKIO_0:()=>document.cookie.includes("__lxG__consent__v2_daisybit="),EVAL_CLINCH_0:()=>document.cookie.includes("ctc_rejected=1"),EVAL_COOKIECONSENT2_TEST:()=>document.cookie.includes("cc_cookie="),EVAL_COOKIECONSENT3_TEST:()=>document.cookie.includes("cc_cookie="),EVAL_COINBASE_0:()=>JSON.parse(decodeURIComponent(document.cookie.match(/cm_(eu|default)_preferences=([0-9a-zA-Z\\{\\}\\[\\]%:]*);?/)[2])).consent.length<=1,EVAL_COMPLIANZ_BANNER_0:()=>document.cookie.includes("cmplz_banner-status=dismissed"),EVAL_COOKIE_LAW_INFO_0:()=>CLI.disableAllCookies()||CLI.reject_close()||!0,EVAL_COOKIE_LAW_INFO_1:()=>-1===document.cookie.indexOf("cookielawinfo-checkbox-non-necessary=yes"),EVAL_COOKIE_LAW_INFO_DETECT:()=>!!window.CLI,EVAL_COOKIE_MANAGER_POPUP_0:()=>!1===JSON.parse(document.cookie.split(";").find((e=>e.trim().startsWith("CookieLevel"))).split("=")[1]).social,EVAL_COOKIEALERT_0:()=>document.querySelector("body").removeAttribute("style")||!0,EVAL_COOKIEALERT_1:()=>document.querySelector("body").removeAttribute("style")||!0,EVAL_COOKIEALERT_2:()=>!0===window.CookieConsent.declined,EVAL_COOKIEFIRST_0:()=>{return!1===(e=JSON.parse(decodeURIComponent(document.cookie.split(";").find((e=>-1!==e.indexOf("cookiefirst"))).trim()).split("=")[1])).performance&&!1===e.functional&&!1===e.advertising;var e},EVAL_COOKIEFIRST_1:()=>document.querySelectorAll("button[data-cookiefirst-accent-color=true][role=checkbox]:not([disabled])").forEach((e=>"true"==e.getAttribute("aria-checked")&&e.click()))||!0,EVAL_COOKIEINFORMATION_0:()=>CookieInformation.declineAllCategories()||!0,EVAL_COOKIEINFORMATION_1:()=>CookieInformation.submitAllCategories()||!0,EVAL_COOKIEINFORMATION_2:()=>document.cookie.includes("CookieInformationConsent="),EVAL_COOKIEYES_0:()=>document.cookie.includes("advertisement:no"),EVAL_DAILYMOTION_0:()=>!!document.cookie.match("dm-euconsent-v2"),EVAL_DNDBEYOND_TEST:()=>document.cookie.includes("cookie-consent=denied"),EVAL_DSGVO_0:()=>!document.cookie.includes("sp_dsgvo_cookie_settings"),EVAL_DUNELM_0:()=>document.cookie.includes("cc_functional=0")&&document.cookie.includes("cc_targeting=0"),EVAL_ETSY_0:()=>document.querySelectorAll(".gdpr-overlay-body input").forEach((e=>{e.checked=!1}))||!0,EVAL_ETSY_1:()=>document.querySelector(".gdpr-overlay-view button[data-wt-overlay-close]").click()||!0,EVAL_EU_COOKIE_COMPLIANCE_0:()=>-1===document.cookie.indexOf("cookie-agreed=2"),EVAL_EU_COOKIE_LAW_0:()=>!document.cookie.includes("euCookie"),EVAL_EZOIC_0:()=>ezCMP.handleAcceptAllClick(),EVAL_EZOIC_1:()=>!!document.cookie.match(/ez-consent-tcf/),EVAL_FIDES_DETECT_POPUP:()=>window.Fides?.initialized,EVAL_GOOGLE_0:()=>!!document.cookie.match(/SOCS=CAE/),EVAL_HEMA_TEST_0:()=>document.cookie.includes("cookies_rejected=1"),EVAL_IUBENDA_0:()=>document.querySelectorAll(".purposes-item input[type=checkbox]:not([disabled])").forEach((e=>{e.checked&&e.click()}))||!0,EVAL_IUBENDA_1:()=>!!document.cookie.match(/_iub_cs-\d+=/),EVAL_IWINK_TEST:()=>document.cookie.includes("cookie_permission_granted=no"),EVAL_JQUERY_COOKIEBAR_0:()=>!document.cookie.includes("cookies-state=accepted"),EVAL_KETCH_TEST:()=>document.cookie.includes("_ketch_consent_v1_"),EVAL_MEDIAVINE_0:()=>document.querySelectorAll('[data-name="mediavine-gdpr-cmp"] input[type=checkbox]').forEach((e=>e.checked&&e.click()))||!0,EVAL_MICROSOFT_0:()=>Array.from(document.querySelectorAll("div > button")).filter((e=>e.innerText.match("Reject|Ablehnen")))[0].click()||!0,EVAL_MICROSOFT_1:()=>Array.from(document.querySelectorAll("div > button")).filter((e=>e.innerText.match("Accept|Annehmen")))[0].click()||!0,EVAL_MICROSOFT_2:()=>!!document.cookie.match("MSCC|GHCC"),EVAL_MOOVE_0:()=>document.querySelectorAll("#moove_gdpr_cookie_modal input").forEach((e=>{e.disabled||(e.checked="moove_gdpr_strict_cookies"===e.name||"moove_gdpr_strict_cookies"===e.id)}))||!0,EVAL_ONENINETWO_0:()=>document.cookie.includes("CC_ADVERTISING=NO")&&document.cookie.includes("CC_ANALYTICS=NO"),EVAL_OPERA_0:()=>document.cookie.includes("cookie_consent_essential=true")&&!document.cookie.includes("cookie_consent_marketing=true"),EVAL_PAYPAL_0:()=>!0===document.cookie.includes("cookie_prefs"),EVAL_PRIMEBOX_0:()=>!document.cookie.includes("cb-enabled=accepted"),EVAL_PUBTECH_0:()=>document.cookie.includes("euconsent-v2")&&(document.cookie.match(/.YAAAAAAAAAAA/)||document.cookie.match(/.aAAAAAAAAAAA/)||document.cookie.match(/.YAAACFgAAAAA/)),EVAL_REDDIT_0:()=>document.cookie.includes("eu_cookie={%22opted%22:true%2C%22nonessential%22:false}"),EVAL_ROBLOX_TEST:()=>document.cookie.includes("RBXcb"),EVAL_SIRDATA_UNBLOCK_SCROLL:()=>(document.documentElement.classList.forEach((e=>{e.startsWith("sd-cmp-")&&document.documentElement.classList.remove(e)})),!0),EVAL_SNIGEL_0:()=>!!document.cookie.match("snconsent"),EVAL_STEAMPOWERED_0:()=>2===JSON.parse(decodeURIComponent(document.cookie.split(";").find((e=>e.trim().startsWith("cookieSettings"))).split("=")[1])).preference_state,EVAL_SVT_TEST:()=>document.cookie.includes('cookie-consent-1={"optedIn":true,"functionality":false,"statistics":false}'),EVAL_TAKEALOT_0:()=>document.body.classList.remove("freeze")||(document.body.style="")||!0,EVAL_TARTEAUCITRON_0:()=>tarteaucitron.userInterface.respondAll(!1)||!0,EVAL_TARTEAUCITRON_1:()=>tarteaucitron.userInterface.respondAll(!0)||!0,EVAL_TARTEAUCITRON_2:()=>document.cookie.match(/tarteaucitron=[^;]*/)?.[0].includes("false"),EVAL_TAUNTON_TEST:()=>document.cookie.includes("taunton_user_consent_submitted=true"),EVAL_TEALIUM_0:()=>void 0!==window.utag&&"object"==typeof utag.gdpr,EVAL_TEALIUM_1:()=>utag.gdpr.setConsentValue(!1)||!0,EVAL_TEALIUM_DONOTSELL:()=>utag.gdpr.dns?.setDnsState(!1)||!0,EVAL_TEALIUM_2:()=>utag.gdpr.setConsentValue(!0)||!0,EVAL_TEALIUM_3:()=>1!==utag.gdpr.getConsentState(),EVAL_TEALIUM_DONOTSELL_CHECK:()=>1!==utag.gdpr.dns?.getDnsState(),EVAL_TESTCMP_0:()=>"button_clicked"===window.results.results[0],EVAL_TESTCMP_COSMETIC_0:()=>"banner_hidden"===window.results.results[0],EVAL_THEFREEDICTIONARY_0:()=>cmpUi.showPurposes()||cmpUi.rejectAll()||!0,EVAL_THEFREEDICTIONARY_1:()=>cmpUi.allowAll()||!0,EVAL_THEVERGE_0:()=>document.cookie.includes("_duet_gdpr_acknowledged=1"),EVAL_UBUNTU_COM_0:()=>document.cookie.includes("_cookies_accepted=essential"),EVAL_UK_COOKIE_CONSENT_0:()=>!document.cookie.includes("catAccCookies"),EVAL_USERCENTRICS_API_0:()=>"object"==typeof UC_UI,EVAL_USERCENTRICS_API_1:()=>!!UC_UI.closeCMP(),EVAL_USERCENTRICS_API_2:()=>!!UC_UI.denyAllConsents(),EVAL_USERCENTRICS_API_3:()=>!!UC_UI.acceptAllConsents(),EVAL_USERCENTRICS_API_4:()=>!!UC_UI.closeCMP(),EVAL_USERCENTRICS_API_5:()=>!0===UC_UI.areAllConsentsAccepted(),EVAL_USERCENTRICS_API_6:()=>!1===UC_UI.areAllConsentsAccepted(),EVAL_USERCENTRICS_BUTTON_0:()=>JSON.parse(localStorage.getItem("usercentrics")).consents.every((e=>e.isEssential||!e.consentStatus)),EVAL_WAITROSE_0:()=>Array.from(document.querySelectorAll("label[id$=cookies-deny-label]")).forEach((e=>e.click()))||!0,EVAL_WAITROSE_1:()=>document.cookie.includes("wtr_cookies_advertising=0")&&document.cookie.includes("wtr_cookies_analytics=0"),EVAL_WP_COOKIE_NOTICE_0:()=>document.cookie.includes("wpl_viewed_cookie=no"),EVAL_XE_TEST:()=>document.cookie.includes("xeConsentState={%22performance%22:false%2C%22marketing%22:false%2C%22compliance%22:false}"),EVAL_XING_0:()=>document.cookie.includes("userConsent=%7B%22marketing%22%3Afalse"),EVAL_YOUTUBE_DESKTOP_0:()=>!!document.cookie.match(/SOCS=CAE/),EVAL_YOUTUBE_MOBILE_0:()=>!!document.cookie.match(/SOCS=CAE/)};var l={main:!0,frame:!1,urlPattern:""},p=class{constructor(e){this.runContext=l,this.autoconsent=e}get hasSelfTest(){throw new Error("Not Implemented")}get isIntermediate(){throw new Error("Not Implemented")}get isCosmetic(){throw new Error("Not Implemented")}mainWorldEval(e){const t=r[e];if(!t)return console.warn("Snippet not found",e),Promise.resolve(!1);const o=this.autoconsent.config.logs;if(this.autoconsent.config.isMainWorld){o.evals&&console.log("inline eval:",e,t);let c=!1;try{c=!!t.call(globalThis)}catch(t){o.evals&&console.error("error evaluating rule",e,t)}return Promise.resolve(c)}const c=`(${t.toString()})()`;return o.evals&&console.log("async eval:",e,c),s(c,e).catch((t=>(o.evals&&console.error("error evaluating rule",e,t),!1)))}checkRunContext(){const e={...l,...this.runContext},t=window.top===window;return!(t&&!e.main)&&(!(!t&&!e.frame)&&!(e.urlPattern&&!window.location.href.match(e.urlPattern)))}detectCmp(){throw new Error("Not Implemented")}async detectPopup(){return!1}optOut(){throw new Error("Not Implemented")}optIn(){throw new Error("Not Implemented")}openCmp(){throw new Error("Not Implemented")}async test(){return Promise.resolve(!0)}click(e,t=!1){return this.autoconsent.domActions.click(e,t)}elementExists(e){return this.autoconsent.domActions.elementExists(e)}elementVisible(e,t){return this.autoconsent.domActions.elementVisible(e,t)}waitForElement(e,t){return this.autoconsent.domActions.waitForElement(e,t)}waitForVisible(e,t,o){return this.autoconsent.domActions.waitForVisible(e,t,o)}waitForThenClick(e,t,o){return this.autoconsent.domActions.waitForThenClick(e,t,o)}wait(e){return this.autoconsent.domActions.wait(e)}hide(e,t){return this.autoconsent.domActions.hide(e,t)}prehide(e){return this.autoconsent.domActions.prehide(e)}undoPrehide(){return this.autoconsent.domActions.undoPrehide()}querySingleReplySelector(e,t){return this.autoconsent.domActions.querySingleReplySelector(e,t)}querySelectorChain(e){return this.autoconsent.domActions.querySelectorChain(e)}elementSelector(e){return this.autoconsent.domActions.elementSelector(e)}},d=class extends p{constructor(e,t){super(t),this.rule=e,this.name=e.name,this.runContext=e.runContext||l}get hasSelfTest(){return!!this.rule.test}get isIntermediate(){return!!this.rule.intermediate}get isCosmetic(){return!!this.rule.cosmetic}get prehideSelectors(){return this.rule.prehideSelectors}async detectCmp(){return!!this.rule.detectCmp&&this._runRulesParallel(this.rule.detectCmp)}async detectPopup(){return!!this.rule.detectPopup&&this._runRulesSequentially(this.rule.detectPopup)}async optOut(){const e=this.autoconsent.config.logs;return!!this.rule.optOut&&(e.lifecycle&&console.log("Initiated optOut()",this.rule.optOut),this._runRulesSequentially(this.rule.optOut))}async optIn(){const e=this.autoconsent.config.logs;return!!this.rule.optIn&&(e.lifecycle&&console.log("Initiated optIn()",this.rule.optIn),this._runRulesSequentially(this.rule.optIn))}async openCmp(){return!!this.rule.openCmp&&this._runRulesSequentially(this.rule.openCmp)}async test(){return this.hasSelfTest?this._runRulesSequentially(this.rule.test):super.test()}async evaluateRuleStep(e){const t=[],o=this.autoconsent.config.logs;if(e.exists&&t.push(this.elementExists(e.exists)),e.visible&&t.push(this.elementVisible(e.visible,e.check)),e.eval){const o=this.mainWorldEval(e.eval);t.push(o)}if(e.waitFor&&t.push(this.waitForElement(e.waitFor,e.timeout)),e.waitForVisible&&t.push(this.waitForVisible(e.waitForVisible,e.timeout,e.check)),e.click&&t.push(this.click(e.click,e.all)),e.waitForThenClick&&t.push(this.waitForThenClick(e.waitForThenClick,e.timeout,e.all)),e.wait&&t.push(this.wait(e.wait)),e.hide&&t.push(this.hide(e.hide,e.method)),e.if){if(!e.if.exists&&!e.if.visible)return console.error("invalid conditional rule",e.if),!1;const c=await this.evaluateRuleStep(e.if);o.rulesteps&&console.log("Condition is",c),c?t.push(this._runRulesSequentially(e.then)):e.else?t.push(this._runRulesSequentially(e.else)):t.push(!0)}if(e.any){for(const t of e.any)if(await this.evaluateRuleStep(t))return!0;return!1}if(0===t.length)return o.errors&&console.warn("Unrecognized rule",e),!1;return(await Promise.all(t)).reduce(((e,t)=>e&&t),!0)}async _runRulesParallel(e){const t=e.map((e=>this.evaluateRuleStep(e)));return(await Promise.all(t)).every((e=>!!e))}async _runRulesSequentially(e){const t=this.autoconsent.config.logs;for(const o of e){t.rulesteps&&console.log("Running rule...",o);const e=await this.evaluateRuleStep(o);if(t.rulesteps&&console.log("...rule result",e),!e&&!o.optional)return!1}return!0}};function u(e="autoconsent-css-rules"){const t=`style#${e}`,o=document.querySelector(t);if(o&&o instanceof HTMLStyleElement)return o;{const t=document.head||document.getElementsByTagName("head")[0]||document.documentElement,o=document.createElement("style");return o.id=e,t.appendChild(o),o}}function m(e,t,o="display"){const c=`${t} { ${"opacity"===o?"opacity: 0":"display: none"} !important; z-index: -1 !important; pointer-events: none !important; } `;return e instanceof HTMLStyleElement&&(e.innerText+=c,t.length>0)}async function h(e,t,o){const c=await e();return!c&&t>0?new Promise((c=>{setTimeout((async()=>{c(h(e,t-1,o))}),o)})):Promise.resolve(c)}function k(e){if(!e)return!1;if(null!==e.offsetParent)return!0;{const t=window.getComputedStyle(e);if("fixed"===t.position&&"none"!==t.display)return!0}return!1}function b(e){const t={enabled:!0,autoAction:"optOut",disabledCmps:[],enablePrehide:!0,enableCosmeticRules:!0,detectRetries:20,isMainWorld:!1,prehideTimeout:2e3,logs:{lifecycle:!1,rulesteps:!1,evals:!1,errors:!0,messages:!1}},o=(c=t,globalThis.structuredClone?structuredClone(c):JSON.parse(JSON.stringify(c)));var c;for(const c of Object.keys(t))void 0!==e[c]&&(o[c]=e[c]);return o}var _="#truste-show-consent",g="#truste-consent-track",y=[class extends p{constructor(e){super(e),this.name="TrustArc-top",this.prehideSelectors=[".trustarc-banner-container",`.truste_popframe,.truste_overlay,.truste_box_overlay,${g}`],this.runContext={main:!0,frame:!1},this._shortcutButton=null,this._optInDone=!1}get hasSelfTest(){return!0}get isIntermediate(){return!this._optInDone&&!this._shortcutButton}get isCosmetic(){return!1}async detectCmp(){const e=this.elementExists(`${_},${g}`);return e&&(this._shortcutButton=document.querySelector("#truste-consent-required")),e}async detectPopup(){return this.elementVisible(`#truste-consent-content,#trustarc-banner-overlay,${g}`,"all")}openFrame(){this.click(_)}async optOut(){return this._shortcutButton?(this._shortcutButton.click(),!0):(m(u(),`.truste_popframe, .truste_overlay, .truste_box_overlay, ${g}`),this.click(_),setTimeout((()=>{u().remove()}),1e4),!0)}async optIn(){return this._optInDone=!0,this.click("#truste-consent-button")}async openCmp(){return!0}async test(){return await this.wait(500),await this.mainWorldEval("EVAL_TRUSTARC_TOP")}},class extends p{constructor(){super(...arguments),this.name="TrustArc-frame",this.runContext={main:!1,frame:!0,urlPattern:"^https://consent-pref\\.trustarc\\.com/\\?"}}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return!0}async detectPopup(){return this.elementVisible("#defaultpreferencemanager","any")&&this.elementVisible(".mainContent","any")}async navigateToSettings(){return await h((async()=>this.elementExists(".shp")||this.elementVisible(".advance","any")||this.elementExists(".switch span:first-child")),10,500),this.elementExists(".shp")&&this.click(".shp"),await this.waitForElement(".prefPanel",5e3),this.elementVisible(".advance","any")&&this.click(".advance"),await h((()=>this.elementVisible(".switch span:first-child","any")),5,1e3)}async optOut(){if(await this.mainWorldEval("EVAL_TRUSTARC_FRAME_TEST"))return!0;let e=3e3;return await this.mainWorldEval("EVAL_TRUSTARC_FRAME_GTM")&&(e=1500),await h((()=>"complete"===document.readyState),20,100),await this.waitForElement(".mainContent[aria-hidden=false]",e),!!this.click(".rejectAll")||(this.elementExists(".prefPanel")&&await this.waitForElement('.prefPanel[style="visibility: visible;"]',e),this.click("#catDetails0")?(this.click(".submit"),this.waitForThenClick("#gwt-debug-close_id",e),!0):this.click(".required")?(this.waitForThenClick("#gwt-debug-close_id",e),!0):(await this.navigateToSettings(),this.click(".switch span:nth-child(1):not(.active)",!0),this.click(".submit"),this.waitForThenClick("#gwt-debug-close_id",10*e),!0))}async optIn(){return this.click(".call")||(await this.navigateToSettings(),this.click(".switch span:nth-child(2)",!0),this.click(".submit"),this.waitForElement("#gwt-debug-close_id",3e5).then((()=>{this.click("#gwt-debug-close_id")}))),!0}async test(){return await this.wait(500),await this.mainWorldEval("EVAL_TRUSTARC_FRAME_TEST")}},class extends p{constructor(){super(...arguments),this.name="Cybotcookiebot",this.prehideSelectors=["#CybotCookiebotDialog,#CybotCookiebotDialogBodyUnderlay,#dtcookie-container,#cookiebanner,#cb-cookieoverlay,.modal--cookie-banner,#cookiebanner_outer,#CookieBanner"]}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return await this.mainWorldEval("EVAL_COOKIEBOT_1")}async detectPopup(){return this.mainWorldEval("EVAL_COOKIEBOT_2")}async optOut(){await this.wait(500);let e=await this.mainWorldEval("EVAL_COOKIEBOT_3");return await this.wait(500),e=e&&await this.mainWorldEval("EVAL_COOKIEBOT_4"),e}async optIn(){return this.elementExists("#dtcookie-container")?this.click(".h-dtcookie-accept"):(this.click(".CybotCookiebotDialogBodyLevelButton:not(:checked):enabled",!0),this.click("#CybotCookiebotDialogBodyLevelButtonAccept"),this.click("#CybotCookiebotDialogBodyButtonAccept"),!0)}async test(){return await this.wait(500),await this.mainWorldEval("EVAL_COOKIEBOT_5")}},class extends p{constructor(){super(...arguments),this.name="Sourcepoint-frame",this.prehideSelectors=["div[id^='sp_message_container_'],.message-overlay","#sp_privacy_manager_container"],this.ccpaNotice=!1,this.ccpaPopup=!1,this.runContext={main:!0,frame:!0}}get hasSelfTest(){return!1}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){const e=new URL(location.href);return e.searchParams.has("message_id")&&"ccpa-notice.sp-prod.net"===e.hostname?(this.ccpaNotice=!0,!0):"ccpa-pm.sp-prod.net"===e.hostname?(this.ccpaPopup=!0,!0):("/index.html"===e.pathname||"/privacy-manager/index.html"===e.pathname||"/ccpa_pm/index.html"===e.pathname)&&(e.searchParams.has("message_id")||e.searchParams.has("requestUUID")||e.searchParams.has("consentUUID"))}async detectPopup(){return!!this.ccpaNotice||(this.ccpaPopup?await this.waitForElement(".priv-save-btn",2e3):(await this.waitForElement(".sp_choice_type_11,.sp_choice_type_12,.sp_choice_type_13,.sp_choice_type_ACCEPT_ALL,.sp_choice_type_SAVE_AND_EXIT",2e3),!this.elementExists(".sp_choice_type_9")))}async optIn(){return await this.waitForElement(".sp_choice_type_11,.sp_choice_type_ACCEPT_ALL",2e3),!!this.click(".sp_choice_type_11")||!!this.click(".sp_choice_type_ACCEPT_ALL")}isManagerOpen(){return"/privacy-manager/index.html"===location.pathname||"/ccpa_pm/index.html"===location.pathname}async optOut(){const e=this.autoconsent.config.logs;if(this.ccpaPopup){const e=document.querySelectorAll(".priv-purpose-container .sp-switch-arrow-block a.neutral.on .right");for(const t of e)t.click();const t=document.querySelectorAll(".priv-purpose-container .sp-switch-arrow-block a.switch-bg.on");for(const e of t)e.click();return this.click(".priv-save-btn")}if(!this.isManagerOpen()){if(!await this.waitForElement(".sp_choice_type_12,.sp_choice_type_13"))return!1;if(!this.elementExists(".sp_choice_type_12"))return this.click(".sp_choice_type_13");this.click(".sp_choice_type_12"),await h((()=>this.isManagerOpen()),200,100)}await this.waitForElement(".type-modal",2e4),this.waitForThenClick(".ccpa-stack .pm-switch[aria-checked=true] .slider",500,!0);try{const e=".sp_choice_type_REJECT_ALL",t=".reject-toggle",o=await Promise.race([this.waitForElement(e,2e3).then((e=>e?0:-1)),this.waitForElement(t,2e3).then((e=>e?1:-1)),this.waitForElement(".pm-features",2e3).then((e=>e?2:-1))]);if(0===o)return await this.wait(1500),this.click(e);1===o?this.click(t):2===o&&(await this.waitForElement(".pm-features",1e4),this.click(".checked > span",!0),this.click(".chevron"))}catch(t){e.errors&&console.warn(t)}return this.click(".sp_choice_type_SAVE_AND_EXIT")}},class extends p{constructor(){super(...arguments),this.name="consentmanager.net",this.prehideSelectors=["#cmpbox,#cmpbox2"],this.apiAvailable=!1}get hasSelfTest(){return this.apiAvailable}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.apiAvailable=await this.mainWorldEval("EVAL_CONSENTMANAGER_1"),!!this.apiAvailable||this.elementExists("#cmpbox")}async detectPopup(){return this.apiAvailable?(await this.wait(500),await this.mainWorldEval("EVAL_CONSENTMANAGER_2")):this.elementVisible("#cmpbox .cmpmore","any")}async optOut(){return await this.wait(500),this.apiAvailable?await this.mainWorldEval("EVAL_CONSENTMANAGER_3"):!!this.click(".cmpboxbtnno")||(this.elementExists(".cmpwelcomeprpsbtn")?(this.click(".cmpwelcomeprpsbtn > a[aria-checked=true]",!0),this.click(".cmpboxbtnsave"),!0):(this.click(".cmpboxbtncustom"),await this.waitForElement(".cmptblbox",2e3),this.click(".cmptdchoice > a[aria-checked=true]",!0),this.click(".cmpboxbtnyescustomchoices"),this.hide("#cmpwrapper,#cmpbox","display"),!0))}async optIn(){return this.apiAvailable?await this.mainWorldEval("EVAL_CONSENTMANAGER_4"):this.click(".cmpboxbtnyes")}async test(){if(this.apiAvailable)return await this.mainWorldEval("EVAL_CONSENTMANAGER_5")}},class extends p{constructor(){super(...arguments),this.name="Evidon"}get hasSelfTest(){return!1}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists("#_evidon_banner")}async detectPopup(){return this.elementVisible("#_evidon_banner","any")}async optOut(){return this.click("#_evidon-decline-button")||(m(u(),"#evidon-prefdiag-overlay,#evidon-prefdiag-background,#_evidon-background"),await this.waitForThenClick("#_evidon-option-button"),await this.waitForElement("#evidon-prefdiag-overlay",5e3),await this.wait(500),await this.waitForThenClick("#evidon-prefdiag-decline")),!0}async optIn(){return this.click("#_evidon-accept-button")}},class extends p{constructor(){super(...arguments),this.name="Onetrust",this.prehideSelectors=["#onetrust-banner-sdk,#onetrust-consent-sdk,.onetrust-pc-dark-filter,.js-consent-banner"],this.runContext={urlPattern:"^(?!.*https://www\\.nba\\.com/)"}}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists("#onetrust-banner-sdk,#onetrust-pc-sdk")}async detectPopup(){return this.elementVisible("#onetrust-banner-sdk,#onetrust-pc-sdk","any")}async optOut(){return this.elementVisible("#onetrust-reject-all-handler,.ot-pc-refuse-all-handler,.js-reject-cookies","any")?this.click("#onetrust-reject-all-handler,.ot-pc-refuse-all-handler,.js-reject-cookies"):(this.elementExists("#onetrust-pc-btn-handler")?this.click("#onetrust-pc-btn-handler"):this.click(".ot-sdk-show-settings,button.js-cookie-settings"),await this.waitForElement("#onetrust-consent-sdk",2e3),await this.wait(1e3),this.click("#onetrust-consent-sdk input.category-switch-handler:checked,.js-editor-toggle-state:checked",!0),await this.wait(1e3),await this.waitForElement(".save-preference-btn-handler,.js-consent-save",2e3),this.click(".save-preference-btn-handler,.js-consent-save"),await this.waitForVisible("#onetrust-banner-sdk",5e3,"none"),!0)}async optIn(){return this.click("#onetrust-accept-btn-handler,#accept-recommended-btn-handler,.js-accept-cookies")}async test(){return await h((()=>this.mainWorldEval("EVAL_ONETRUST_1")),10,500)}},class extends p{constructor(){super(...arguments),this.name="Klaro",this.prehideSelectors=[".klaro"],this.settingsOpen=!1}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists(".klaro > .cookie-modal")?(this.settingsOpen=!0,!0):this.elementExists(".klaro > .cookie-notice")}async detectPopup(){return this.elementVisible(".klaro > .cookie-notice,.klaro > .cookie-modal","any")}async optOut(){return!!await this.mainWorldEval("EVAL_KLARO_TRY_API_OPT_OUT")||(!!this.click(".klaro .cn-decline")||(await this.mainWorldEval("EVAL_KLARO_OPEN_POPUP"),!!this.click(".klaro .cn-decline")||(this.click(".cm-purpose:not(.cm-toggle-all) > input:not(.half-checked,.required,.only-required),.cm-purpose:not(.cm-toggle-all) > div > input:not(.half-checked,.required,.only-required)",!0),this.click(".cm-btn-accept,.cm-button"))))}async optIn(){return!!this.click(".klaro .cm-btn-accept-all")||(this.settingsOpen?(this.click(".cm-purpose:not(.cm-toggle-all) > input.half-checked",!0),this.click(".cm-btn-accept")):this.click(".klaro .cookie-notice .cm-btn-success"))}async test(){return await this.mainWorldEval("EVAL_KLARO_1")}},class extends p{constructor(){super(...arguments),this.name="Uniconsent"}get prehideSelectors(){return[".unic",".modal:has(.unic)"]}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists(".unic .unic-box,.unic .unic-bar,.unic .unic-modal")}async detectPopup(){return this.elementVisible(".unic .unic-box,.unic .unic-bar,.unic .unic-modal","any")}async optOut(){if(await this.waitForElement(".unic button",1e3),document.querySelectorAll(".unic button").forEach((e=>{const t=e.textContent;(t.includes("Manage Options")||t.includes("Optionen verwalten"))&&e.click()})),await this.waitForElement(".unic input[type=checkbox]",1e3)){await this.waitForElement(".unic button",1e3),document.querySelectorAll(".unic input[type=checkbox]").forEach((e=>{e.checked&&e.click()}));for(const e of document.querySelectorAll(".unic button")){const t=e.textContent;for(const o of["Confirm Choices","Save Choices","Auswahl speichern"])if(t.includes(o))return e.click(),await this.wait(500),!0}}return!1}async optIn(){return this.waitForThenClick(".unic #unic-agree")}async test(){await this.wait(1e3);return!this.elementExists(".unic .unic-box,.unic .unic-bar")}},class extends p{constructor(){super(...arguments),this.prehideSelectors=[".cmp-root"],this.name="Conversant"}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists(".cmp-root .cmp-receptacle")}async detectPopup(){return this.elementVisible(".cmp-root .cmp-receptacle","any")}async optOut(){if(!await this.waitForThenClick(".cmp-main-button:not(.cmp-main-button--primary)"))return!1;if(!await this.waitForElement(".cmp-view-tab-tabs"))return!1;await this.waitForThenClick(".cmp-view-tab-tabs > :first-child"),await this.waitForThenClick(".cmp-view-tab-tabs > .cmp-view-tab--active:first-child");for(const e of Array.from(document.querySelectorAll(".cmp-accordion-item"))){e.querySelector(".cmp-accordion-item-title").click(),await h((()=>!!e.querySelector(".cmp-accordion-item-content.cmp-active")),10,50);const t=e.querySelector(".cmp-accordion-item-content.cmp-active");t.querySelectorAll(".cmp-toggle-actions .cmp-toggle-deny:not(.cmp-toggle-deny--active)").forEach((e=>e.click())),t.querySelectorAll(".cmp-toggle-actions .cmp-toggle-checkbox:not(.cmp-toggle-checkbox--active)").forEach((e=>e.click()))}return await this.click(".cmp-main-button:not(.cmp-main-button--primary)"),!0}async optIn(){return this.waitForThenClick(".cmp-main-button.cmp-main-button--primary")}async test(){return document.cookie.includes("cmp-data=0")}},class extends p{constructor(){super(...arguments),this.name="tiktok.com",this.runContext={urlPattern:"tiktok"}}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}getShadowRoot(){const e=document.querySelector("tiktok-cookie-banner");return e?e.shadowRoot:null}async detectCmp(){return this.elementExists("tiktok-cookie-banner")}async detectPopup(){return k(this.getShadowRoot().querySelector(".tiktok-cookie-banner"))}async optOut(){const e=this.autoconsent.config.logs,t=this.getShadowRoot().querySelector(".button-wrapper button:first-child");return t?(e.rulesteps&&console.log("[clicking]",t),t.click(),!0):(e.errors&&console.log("no decline button found"),!1)}async optIn(){const e=this.autoconsent.config.logs,t=this.getShadowRoot().querySelector(".button-wrapper button:last-child");return t?(e.rulesteps&&console.log("[clicking]",t),t.click(),!0):(e.errors&&console.log("no accept button found"),!1)}async test(){const e=document.cookie.match(/cookie-consent=([^;]+)/);if(!e)return!1;const t=JSON.parse(decodeURIComponent(e[1]));return Object.values(t).every((e=>"boolean"!=typeof e||!1===e))}},class extends p{constructor(){super(...arguments),this.runContext={urlPattern:"^https://(www\\.)?airbnb\\.[^/]+/"},this.prehideSelectors=["div[data-testid=main-cookies-banner-container]",'div:has(> div:first-child):has(> div:last-child):has(> section [data-testid="strictly-necessary-cookies"])']}get hasSelfTest(){return!0}get isIntermediate(){return!1}get isCosmetic(){return!1}async detectCmp(){return this.elementExists("div[data-testid=main-cookies-banner-container]")}async detectPopup(){return this.elementVisible("div[data-testid=main-cookies-banner-container","any")}async optOut(){let e;for(await this.waitForThenClick("div[data-testid=main-cookies-banner-container] button._snbhip0");e=document.querySelector("[data-testid=modal-container] button[aria-checked=true]:not([disabled])");)e.click();return this.waitForThenClick("button[data-testid=save-btn]")}async optIn(){return this.waitForThenClick("div[data-testid=main-cookies-banner-container] button._148dgdpk")}async test(){return await h((()=>!!document.cookie.match("OptanonAlertBoxClosed")),20,200)}},class extends p{constructor(){super(...arguments),this.name="tumblr-com",this.runContext={urlPattern:"^https://(www\\.)?tumblr\\.com/"}}get hasSelfTest(){return!1}get isIntermediate(){return!1}get isCosmetic(){return!1}get prehideSelectors(){return["#cmp-app-container"]}async detectCmp(){return this.elementExists("#cmp-app-container")}async detectPopup(){return this.elementVisible("#cmp-app-container","any")}async optOut(){let e=document.querySelector("#cmp-app-container iframe"),t=e.contentDocument?.querySelector(".cmp-components-button.is-secondary");return!!t&&(t.click(),await h((()=>!!document.querySelector("#cmp-app-container iframe").contentDocument?.querySelector(".cmp__dialog input")),5,500),e=document.querySelector("#cmp-app-container iframe"),t=e.contentDocument?.querySelector(".cmp-components-button.is-secondary"),!!t&&(t.click(),!0))}async optIn(){const e=document.querySelector("#cmp-app-container iframe").contentDocument.querySelector(".cmp-components-button.is-primary");return!!e&&(e.click(),!0)}}];var w=[{name:"192.com",detectCmp:[{exists:".ont-cookies"}],detectPopup:[{visible:".ont-cookies"}],optIn:[{click:".ont-btn-main.ont-cookies-btn.js-ont-btn-ok2"}],optOut:[{click:".ont-cookes-btn-manage"},{click:".ont-btn-main.ont-cookies-btn.js-ont-btn-choose"}],test:[{eval:"EVAL_ONENINETWO_0"}]},{name:"1password-com",cosmetic:!0,prehideSelectors:['footer #footer-root [aria-label="Cookie Consent"]'],detectCmp:[{exists:'footer #footer-root [aria-label="Cookie Consent"]'}],detectPopup:[{visible:'footer #footer-root [aria-label="Cookie Consent"]'}],optIn:[{click:'footer #footer-root [aria-label="Cookie Consent"] button'}],optOut:[{hide:'footer #footer-root [aria-label="Cookie Consent"]'}]},{name:"abconcerts.be",vendorUrl:"https://unknown",intermediate:!1,prehideSelectors:["dialog.cookie-consent"],detectCmp:[{exists:"dialog.cookie-consent form.cookie-consent__form"}],detectPopup:[{visible:"dialog.cookie-consent form.cookie-consent__form"}],optIn:[{waitForThenClick:"dialog.cookie-consent form.cookie-consent__form button[value=yes]"}],optOut:[{if:{exists:"dialog.cookie-consent form.cookie-consent__form button[value=no]"},then:[{click:"dialog.cookie-consent form.cookie-consent__form button[value=no]"}],else:[{click:"dialog.cookie-consent form.cookie-consent__form button.cookie-consent__options-toggle"},{waitForThenClick:'dialog.cookie-consent form.cookie-consent__form button[value="save_options"]'}]}]},{name:"acris",prehideSelectors:["div.acris-cookie-consent"],detectCmp:[{exists:"[data-acris-cookie-consent]"}],detectPopup:[{visible:".acris-cookie-consent.is--modal"}],optIn:[{waitForVisible:"#ccConsentAcceptAllButton",check:"any"},{wait:500},{waitForThenClick:"#ccConsentAcceptAllButton"}],optOut:[{waitForVisible:"#ccAcceptOnlyFunctional",check:"any"},{wait:500},{waitForThenClick:"#ccAcceptOnlyFunctional"}]},{name:"activobank.pt",runContext:{urlPattern:"^https://(www\\.)?activobank\\.pt"},prehideSelectors:["aside#cookies,.overlay-cookies"],detectCmp:[{exists:"#cookies .cookies-btn"}],detectPopup:[{visible:"#cookies #submitCookies"}],optIn:[{waitForThenClick:"#cookies #submitCookies"}],optOut:[{waitForThenClick:"#cookies #rejectCookies"}]},{name:"Adroll",prehideSelectors:["#adroll_consent_container"],detectCmp:[{exists:"#adroll_consent_container"}],detectPopup:[{visible:"#adroll_consent_container"}],optIn:[{waitForThenClick:"#adroll_consent_accept"}],optOut:[{waitForThenClick:"#adroll_consent_reject"}],test:[{eval:"EVAL_ADROLL_0"}]},{name:"affinity.serif.com",detectCmp:[{exists:".c-cookie-banner button[data-qa='allow-all-cookies']"}],detectPopup:[{visible:".c-cookie-banner"}],optIn:[{click:'button[data-qa="allow-all-cookies"]'}],optOut:[{click:'button[data-qa="manage-cookies"]'},{waitFor:'.c-cookie-banner ~ [role="dialog"]'},{waitForThenClick:'.c-cookie-banner ~ [role="dialog"] input[type="checkbox"][value="true"]',all:!0},{click:'.c-cookie-banner ~ [role="dialog"] .c-modal__action button'}],test:[{wait:500},{eval:"EVAL_AFFINITY_SERIF_COM_0"}]},{name:"agolde.com",cosmetic:!0,prehideSelectors:["#modal-1 div[data-micromodal-close]"],detectCmp:[{exists:"#modal-1 div[aria-labelledby=modal-1-title]"}],detectPopup:[{exists:"#modal-1 div[data-micromodal-close]"}],optIn:[{click:'button[aria-label="Close modal"]'}],optOut:[{hide:"#modal-1 div[data-micromodal-close]"}]},{name:"aliexpress",vendorUrl:"https://aliexpress.com/",runContext:{urlPattern:"^https://.*\\.aliexpress\\.com/"},prehideSelectors:["#gdpr-new-container"],detectCmp:[{exists:"#gdpr-new-container"}],detectPopup:[{visible:"#gdpr-new-container"}],optIn:[{waitForThenClick:"#gdpr-new-container .btn-accept"}],optOut:[{waitForThenClick:"#gdpr-new-container .btn-more"},{waitFor:"#gdpr-new-container .gdpr-dialog-switcher"},{click:"#gdpr-new-container .switcher-on",all:!0,optional:!0},{click:"#gdpr-new-container .btn-save"}]},{name:"almacmp",prehideSelectors:["#alma-cmpv2-container"],detectCmp:[{exists:"#alma-cmpv2-container"}],detectPopup:[{visible:"#alma-cmpv2-container #almacmp-modal-layer1"}],optIn:[{waitForThenClick:"#alma-cmpv2-container #almacmp-modal-layer1 #almacmp-modalConfirmBtn"}],optOut:[{waitForThenClick:"#alma-cmpv2-container #almacmp-modal-layer1 #almacmp-modalSettingBtn"},{waitFor:"#alma-cmpv2-container #almacmp-modal-layer2"},{waitForThenClick:"#alma-cmpv2-container #almacmp-modal-layer2 #almacmp-reject-all-layer2"}],test:[{eval:"EVAL_ALMACMP_0"}]},{name:"altium.com",cosmetic:!0,prehideSelectors:[".altium-privacy-bar"],detectCmp:[{exists:".altium-privacy-bar"}],detectPopup:[{exists:".altium-privacy-bar"}],optIn:[{click:"a.altium-privacy-bar__btn"}],optOut:[{hide:".altium-privacy-bar"}]},{name:"amazon.com",prehideSelectors:['span[data-action="sp-cc"][data-sp-cc*="rejectAllAction"]'],detectCmp:[{exists:'span[data-action="sp-cc"][data-sp-cc*="rejectAllAction"]'}],detectPopup:[{visible:'span[data-action="sp-cc"][data-sp-cc*="rejectAllAction"]'}],optIn:[{waitForVisible:"#sp-cc-accept"},{wait:500},{click:"#sp-cc-accept"}],optOut:[{waitForVisible:"#sp-cc-rejectall-link"},{wait:500},{click:"#sp-cc-rejectall-link"}]},{name:"aquasana.com",prehideSelectors:["#consent-tracking"],detectCmp:[{exists:"#consent-tracking"}],detectPopup:[{exists:"#consent-tracking"}],optIn:[{waitForThenClick:"#consent-tracking .affirm.btn"}],optOut:[{if:{exists:"#consent-tracking .decline.btn"},then:[{click:"#consent-tracking .decline.btn"}],else:[{hide:"#consent-tracking"}]}]},{name:"arbeitsagentur",vendorUrl:"https://www.arbeitsagentur.de/",prehideSelectors:[".modal-open bahf-cookie-disclaimer-dpl3"],detectCmp:[{exists:"bahf-cookie-disclaimer-dpl3"}],detectPopup:[{visible:"bahf-cookie-disclaimer-dpl3"}],optIn:[{waitForThenClick:["bahf-cookie-disclaimer-dpl3","bahf-cd-modal-dpl3 .ba-btn-primary"]}],optOut:[{waitForThenClick:["bahf-cookie-disclaimer-dpl3","bahf-cd-modal-dpl3 .ba-btn-contrast"]}],test:[{eval:"EVAL_ARBEITSAGENTUR_TEST"}]},{name:"asus",vendorUrl:"https://www.asus.com/",runContext:{urlPattern:"^https://www\\.asus\\.com/"},prehideSelectors:["#cookie-policy-info,#cookie-policy-info-bg"],detectCmp:[{exists:"#cookie-policy-info"}],detectPopup:[{visible:"#cookie-policy-info"}],optIn:[{waitForThenClick:'#cookie-policy-info [data-agree="Accept Cookies"]'}],optOut:[{if:{exists:"#cookie-policy-info .btn-reject"},then:[{waitForThenClick:"#cookie-policy-info .btn-reject"}],else:[{waitForThenClick:"#cookie-policy-info .btn-setting"},{waitForThenClick:'#cookie-policy-lightbox-wrapper [data-agree="Save Settings"]'}]}]},{name:"athlinks-com",runContext:{urlPattern:"^https://(www\\.)?athlinks\\.com/"},cosmetic:!0,prehideSelectors:["#footer-container ~ div"],detectCmp:[{exists:"#footer-container ~ div"}],detectPopup:[{visible:"#footer-container > div"}],optIn:[{click:"#footer-container ~ div button"}],optOut:[{hide:"#footer-container ~ div"}]},{name:"ausopen.com",cosmetic:!0,detectCmp:[{exists:".gdpr-popup__message"}],detectPopup:[{visible:".gdpr-popup__message"}],optOut:[{hide:".gdpr-popup__message"}],optIn:[{click:".gdpr-popup__message button"}]},{name:"automattic-cmp-optout",prehideSelectors:['form[class*="cookie-banner"][method="post"]'],detectCmp:[{exists:'form[class*="cookie-banner"][method="post"]'}],detectPopup:[{visible:'form[class*="cookie-banner"][method="post"]'}],optIn:[{click:'a[class*="accept-all-button"]'}],optOut:[{click:'form[class*="cookie-banner"] div[class*="simple-options"] a[class*="customize-button"]'},{waitForThenClick:"input[type=checkbox][checked]:not([disabled])",all:!0},{click:'a[class*="accept-selection-button"]'}]},{name:"aws.amazon.com",prehideSelectors:["#awsccc-cb-content","#awsccc-cs-container","#awsccc-cs-modalOverlay","#awsccc-cs-container-inner"],detectCmp:[{exists:"#awsccc-cb-content"}],detectPopup:[{visible:"#awsccc-cb-content"}],optIn:[{click:"button[data-id=awsccc-cb-btn-accept"}],optOut:[{click:"button[data-id=awsccc-cb-btn-customize]"},{waitFor:"input[aria-checked]"},{click:"input[aria-checked=true]",all:!0,optional:!0},{click:"button[data-id=awsccc-cs-btn-save]"}]},{name:"axeptio",prehideSelectors:[".axeptio_widget"],detectCmp:[{exists:".axeptio_widget"}],detectPopup:[{visible:".axeptio_widget"}],optIn:[{waitFor:".axeptio-widget--open"},{click:"button#axeptio_btn_acceptAll"}],optOut:[{waitFor:".axeptio-widget--open"},{click:"button#axeptio_btn_dismiss"}],test:[{eval:"EVAL_AXEPTIO_0"}]},{name:"baden-wuerttemberg.de",prehideSelectors:[".cookie-alert.t-dark"],cosmetic:!0,detectCmp:[{exists:".cookie-alert.t-dark"}],detectPopup:[{visible:".cookie-alert.t-dark"}],optIn:[{click:".cookie-alert__form input:not([disabled]):not([checked])"},{click:".cookie-alert__button button"}],optOut:[{hide:".cookie-alert.t-dark"}]},{name:"bahn-de",vendorUrl:"https://www.bahn.de/",cosmetic:!1,runContext:{main:!0,frame:!1,urlPattern:"^https://(www\\.)?bahn\\.de/"},intermediate:!1,prehideSelectors:[],detectCmp:[{exists:["body > div:first-child","#consent-layer"]}],detectPopup:[{visible:["body > div:first-child","#consent-layer"]}],optIn:[{waitForThenClick:["body > div:first-child","#consent-layer .js-accept-all-cookies"]}],optOut:[{waitForThenClick:["body > div:first-child","#consent-layer .js-accept-essential-cookies"]}],test:[{eval:"EVAL_BAHN_TEST"}]},{name:"bbb.org",runContext:{urlPattern:"^https://www\\.bbb\\.org/"},cosmetic:!0,prehideSelectors:['div[aria-label="use of cookies on bbb.org"]'],detectCmp:[{exists:'div[aria-label="use of cookies on bbb.org"]'}],detectPopup:[{visible:'div[aria-label="use of cookies on bbb.org"]'}],optIn:[{click:'div[aria-label="use of cookies on bbb.org"] button.bds-button-unstyled span.visually-hidden'}],optOut:[{hide:'div[aria-label="use of cookies on bbb.org"]'}]},{name:"bing.com",prehideSelectors:["#bnp_container"],detectCmp:[{exists:"#bnp_cookie_banner"}],detectPopup:[{visible:"#bnp_cookie_banner"}],optIn:[{click:"#bnp_btn_accept"}],optOut:[{click:"#bnp_btn_preference"},{click:"#mcp_savesettings"}],test:[{eval:"EVAL_BING_0"}]},{name:"blocksy",vendorUrl:"https://creativethemes.com/blocksy/docs/extensions/cookies-consent/",cosmetic:!1,runContext:{main:!0,frame:!1},intermediate:!1,prehideSelectors:[".cookie-notification"],detectCmp:[{exists:"#blocksy-ext-cookies-consent-styles-css"}],detectPopup:[{visible:".cookie-notification"}],optIn:[{click:".cookie-notification .ct-cookies-decline-button"}],optOut:[{waitForThenClick:".cookie-notification .ct-cookies-decline-button"}],test:[{eval:"EVAL_BLOCKSY_0"}]},{name:"borlabs",detectCmp:[{exists:"._brlbs-block-content"}],detectPopup:[{visible:"._brlbs-bar-wrap,._brlbs-box-wrap"}],optIn:[{click:"a[data-cookie-accept-all]"}],optOut:[{click:"a[data-cookie-individual]"},{waitForVisible:".cookie-preference"},{click:"input[data-borlabs-cookie-checkbox]:checked",all:!0,optional:!0},{click:"#CookiePrefSave"},{wait:500}],prehideSelectors:["#BorlabsCookieBox"],test:[{eval:"EVAL_BORLABS_0"}]},{name:"bundesregierung.de",prehideSelectors:[".bpa-cookie-banner"],detectCmp:[{exists:".bpa-cookie-banner"}],detectPopup:[{visible:".bpa-cookie-banner .bpa-module-full-hero"}],optIn:[{click:".bpa-accept-all-button"}],optOut:[{wait:500,comment:"click is not immediately recognized"},{waitForThenClick:".bpa-close-button"}],test:[{eval:"EVAL_BUNDESREGIERUNG_DE_0"}]},{name:"burpee.com",cosmetic:!0,prehideSelectors:["#notice-cookie-block"],detectCmp:[{exists:"#notice-cookie-block"}],detectPopup:[{exists:"#html-body #notice-cookie-block"}],optIn:[{click:"#btn-cookie-allow"}],optOut:[{hide:"#html-body #notice-cookie-block, #notice-cookie"}]},{name:"canva.com",prehideSelectors:['div[role="dialog"] a[data-anchor-id="cookie-policy"]'],detectCmp:[{exists:'div[role="dialog"] a[data-anchor-id="cookie-policy"]'}],detectPopup:[{exists:'div[role="dialog"] a[data-anchor-id="cookie-policy"]'}],optIn:[{click:'div[role="dialog"] button:nth-child(1)'}],optOut:[{if:{exists:'div[role="dialog"] button:nth-child(3)'},then:[{click:'div[role="dialog"] button:nth-child(2)'}],else:[{click:'div[role="dialog"] button:nth-child(2)'},{waitFor:'div[role="dialog"] a[data-anchor-id="cookie-policy"]'},{waitFor:'div[role="dialog"] button[role=switch]'},{click:'div[role="dialog"] button:nth-child(2):not([role])'},{click:'div[role="dialog"] div:last-child button:only-child'}]}],test:[{eval:"EVAL_CANVA_0"}]},{name:"canyon.com",runContext:{urlPattern:"^https://www\\.canyon\\.com/"},prehideSelectors:["div.modal.cookiesModal.is-open"],detectCmp:[{exists:"div.modal.cookiesModal.is-open"}],detectPopup:[{visible:"div.modal.cookiesModal.is-open"}],optIn:[{click:'div.cookiesModal__buttonWrapper > button[data-closecause="close-by-submit"]'}],optOut:[{click:'div.cookiesModal__buttonWrapper > button[data-closecause="close-by-manage-cookies"]'},{waitForThenClick:"button#js-manage-data-privacy-save-button"}]},{name:"cc-banner-springer",prehideSelectors:[".cc-banner[data-cc-banner]"],detectCmp:[{exists:".cc-banner[data-cc-banner]"}],detectPopup:[{visible:".cc-banner[data-cc-banner]"}],optIn:[{waitForThenClick:".cc-banner[data-cc-banner] button[data-cc-action=accept]"}],optOut:[{if:{exists:".cc-banner[data-cc-banner] button[data-cc-action=reject]"},then:[{click:".cc-banner[data-cc-banner] button[data-cc-action=reject]"}],else:[{waitForThenClick:".cc-banner[data-cc-banner] button[data-cc-action=preferences]"},{waitFor:".cc-preferences[data-cc-preferences]"},{click:".cc-preferences[data-cc-preferences] input[type=radio][data-cc-action=toggle-category][value=off]",all:!0,optional:!0},{if:{exists:".cc-preferences[data-cc-preferences] button[data-cc-action=reject]"},then:[{click:".cc-preferences[data-cc-preferences] button[data-cc-action=reject]"}],else:[{click:".cc-preferences[data-cc-preferences] button[data-cc-action=save]"}]}]}],test:[{eval:"EVAL_CC_BANNER2_0"}]},{name:"cc_banner",cosmetic:!0,prehideSelectors:[".cc_banner-wrapper"],detectCmp:[{exists:".cc_banner-wrapper"}],detectPopup:[{visible:".cc_banner"}],optIn:[{click:".cc_btn_accept_all"}],optOut:[{hide:".cc_banner-wrapper"}]},{name:"check24-partnerprogramm-de",prehideSelectors:["[data-modal-content]:has([data-toggle-target^='cookie'])"],detectCmp:[{exists:"[data-toggle-target^='cookie']"}],detectPopup:[{visible:"[data-toggle-target^='cookie']",check:"any"}],optIn:[{waitForThenClick:"[data-cookie-accept-all]"}],optOut:[{waitForThenClick:"[data-cookie-dismiss-all]"}]},{name:"ciaopeople.it",prehideSelectors:["#cp-gdpr-choices"],detectCmp:[{exists:"#cp-gdpr-choices"}],detectPopup:[{visible:"#cp-gdpr-choices"}],optIn:[{waitForThenClick:".gdpr-btm__right > button:nth-child(2)"}],optOut:[{waitForThenClick:".gdpr-top-content > button"},{waitFor:".gdpr-top-back"},{waitForThenClick:".gdpr-btm__right > button:nth-child(1)"}],test:[{visible:"#cp-gdpr-choices",check:"none"}]},{vendorUrl:"https://www.civicuk.com/cookie-control/",name:"civic-cookie-control",prehideSelectors:["#ccc-module,#ccc-overlay"],detectCmp:[{exists:"#ccc-module"}],detectPopup:[{visible:"#ccc"},{visible:"#ccc-module"}],optOut:[{click:"#ccc-reject-settings"}],optIn:[{click:"#ccc-recommended-settings"}]},{name:"click.io",prehideSelectors:["#cl-consent"],detectCmp:[{exists:"#cl-consent"}],detectPopup:[{visible:"#cl-consent"}],optIn:[{waitForThenClick:'#cl-consent [data-role="b_agree"]'}],optOut:[{waitFor:'#cl-consent [data-role="b_options"]'},{wait:500},{click:'#cl-consent [data-role="b_options"]'},{waitFor:'.cl-consent-popup.cl-consent-visible [data-role="alloff"]'},{click:'.cl-consent-popup.cl-consent-visible [data-role="alloff"]',all:!0},{click:'[data-role="b_save"]'}],test:[{eval:"EVAL_CLICKIO_0",comment:"TODO: this only checks if we interacted at all"}]},{name:"clinch",intermediate:!1,runContext:{frame:!1,main:!0},prehideSelectors:[".consent-modal[role=dialog]"],detectCmp:[{exists:".consent-modal[role=dialog]"}],detectPopup:[{visible:".consent-modal[role=dialog]"}],optIn:[{click:"#consent_agree"}],optOut:[{if:{exists:"#consent_reject"},then:[{click:"#consent_reject"}],else:[{click:"#manage_cookie_preferences"},{click:"#cookie_consent_preferences input:checked",all:!0,optional:!0},{click:"#consent_save"}]}],test:[{eval:"EVAL_CLINCH_0"}]},{name:"clustrmaps.com",runContext:{urlPattern:"^https://(www\\.)?clustrmaps\\.com/"},cosmetic:!0,prehideSelectors:["#gdpr-cookie-message"],detectCmp:[{exists:"#gdpr-cookie-message"}],detectPopup:[{visible:"#gdpr-cookie-message"}],optIn:[{click:"button#gdpr-cookie-accept"}],optOut:[{hide:"#gdpr-cookie-message"}]},{name:"coinbase",intermediate:!1,runContext:{frame:!0,main:!0,urlPattern:"^https://(www|help)\\.coinbase\\.com"},prehideSelectors:[],detectCmp:[{exists:"div[class^=CookieBannerContent__Container]"}],detectPopup:[{visible:"div[class^=CookieBannerContent__Container]"}],optIn:[{click:"div[class^=CookieBannerContent__CTA] :nth-last-child(1)"}],optOut:[{click:"button[class^=CookieBannerContent__Settings]"},{click:"div[class^=CookiePreferencesModal__CategoryContainer] input:checked",all:!0,optional:!0},{click:"div[class^=CookiePreferencesModal__ButtonContainer] > button"}],test:[{eval:"EVAL_COINBASE_0"}]},{name:"Complianz banner",prehideSelectors:["#cmplz-cookiebanner-container"],detectCmp:[{exists:"#cmplz-cookiebanner-container .cmplz-cookiebanner"}],detectPopup:[{visible:"#cmplz-cookiebanner-container .cmplz-cookiebanner",check:"any"}],optIn:[{waitForThenClick:".cmplz-cookiebanner .cmplz-accept"}],optOut:[{waitForThenClick:".cmplz-cookiebanner .cmplz-deny"}],test:[{eval:"EVAL_COMPLIANZ_BANNER_0"}]},{name:"Complianz categories",prehideSelectors:['.cc-type-categories[aria-describedby="cookieconsent:desc"]'],detectCmp:[{exists:'.cc-type-categories[aria-describedby="cookieconsent:desc"]'}],detectPopup:[{visible:'.cc-type-categories[aria-describedby="cookieconsent:desc"]'}],optIn:[{any:[{click:".cc-accept-all"},{click:".cc-allow-all"},{click:".cc-allow"},{click:".cc-dismiss"}]}],optOut:[{if:{exists:'.cc-type-categories[aria-describedby="cookieconsent:desc"] .cc-dismiss'},then:[{click:".cc-dismiss"}],else:[{click:".cc-type-categories input[type=checkbox]:not([disabled]):checked",all:!0,optional:!0},{click:".cc-save"}]}]},{name:"Complianz notice",prehideSelectors:['.cc-type-info[aria-describedby="cookieconsent:desc"]'],cosmetic:!0,detectCmp:[{exists:'.cc-type-info[aria-describedby="cookieconsent:desc"] .cc-compliance .cc-btn'}],detectPopup:[{visible:'.cc-type-info[aria-describedby="cookieconsent:desc"] .cc-compliance .cc-btn'}],optIn:[{click:".cc-accept-all",optional:!0},{click:".cc-allow",optional:!0},{click:".cc-dismiss",optional:!0}],optOut:[{if:{exists:".cc-deny"},then:[{click:".cc-deny"}],else:[{hide:'[aria-describedby="cookieconsent:desc"]'}]}]},{name:"Complianz opt-both",prehideSelectors:['[aria-describedby="cookieconsent:desc"] .cc-type-opt-both'],detectCmp:[{exists:'[aria-describedby="cookieconsent:desc"] .cc-type-opt-both'}],detectPopup:[{visible:'[aria-describedby="cookieconsent:desc"] .cc-type-opt-both'}],optIn:[{click:".cc-accept-all",optional:!0},{click:".cc-allow",optional:!0},{click:".cc-dismiss",optional:!0}],optOut:[{waitForThenClick:".cc-deny"}]},{name:"Complianz opt-out",prehideSelectors:['[aria-describedby="cookieconsent:desc"].cc-type-opt-out'],detectCmp:[{exists:'[aria-describedby="cookieconsent:desc"].cc-type-opt-out'}],detectPopup:[{visible:'[aria-describedby="cookieconsent:desc"].cc-type-opt-out'}],optIn:[{click:".cc-accept-all",optional:!0},{click:".cc-allow",optional:!0},{click:".cc-dismiss",optional:!0}],optOut:[{if:{exists:".cc-deny"},then:[{click:".cc-deny"}],else:[{if:{exists:".cmp-pref-link"},then:[{click:".cmp-pref-link"},{waitForThenClick:".cmp-body [id*=rejectAll]"},{waitForThenClick:".cmp-body .cmp-save-btn"}]}]}]},{name:"Complianz optin",prehideSelectors:['.cc-type-opt-in[aria-describedby="cookieconsent:desc"]'],detectCmp:[{exists:'.cc-type-opt-in[aria-describedby="cookieconsent:desc"]'}],detectPopup:[{visible:'.cc-type-opt-in[aria-describedby="cookieconsent:desc"]'}],optIn:[{any:[{click:".cc-accept-all"},{click:".cc-allow"},{click:".cc-dismiss"}]}],optOut:[{if:{visible:".cc-deny"},then:[{click:".cc-deny"}],else:[{if:{visible:".cc-settings"},then:[{waitForThenClick:".cc-settings"},{waitForVisible:".cc-settings-view"},{click:".cc-settings-view input[type=checkbox]:not([disabled]):checked",all:!0,optional:!0},{click:".cc-settings-view .cc-btn-accept-selected"}],else:[{click:".cc-dismiss"}]}]}]},{name:"cookie-law-info",prehideSelectors:["#cookie-law-info-bar"],detectCmp:[{exists:"#cookie-law-info-bar"},{eval:"EVAL_COOKIE_LAW_INFO_DETECT"}],detectPopup:[{visible:"#cookie-law-info-bar"}],optIn:[{click:'[data-cli_action="accept_all"]'}],optOut:[{hide:"#cookie-law-info-bar"},{eval:"EVAL_COOKIE_LAW_INFO_0"}],test:[{eval:"EVAL_COOKIE_LAW_INFO_1"}]},{name:"cookie-manager-popup",cosmetic:!1,runContext:{main:!0,frame:!1},intermediate:!1,detectCmp:[{exists:"#notice-cookie-block #allow-functional-cookies, #notice-cookie-block #btn-cookie-settings"}],detectPopup:[{visible:"#notice-cookie-block"}],optIn:[{click:"#btn-cookie-allow"}],optOut:[{if:{exists:"#allow-functional-cookies"},then:[{click:"#allow-functional-cookies"}],else:[{waitForThenClick:"#btn-cookie-settings"},{waitForVisible:".modal-body"},{click:'.modal-body input:checked, .switch[data-switch="on"]',all:!0,optional:!0},{click:'[role="dialog"] .modal-footer button'}]}],prehideSelectors:["#btn-cookie-settings"],test:[{eval:"EVAL_COOKIE_MANAGER_POPUP_0"}]},{name:"cookie-notice",prehideSelectors:["#cookie-notice"],cosmetic:!0,detectCmp:[{visible:"#cookie-notice .cookie-notice-container"}],detectPopup:[{visible:"#cookie-notice"}],optIn:[{click:"#cn-accept-cookie"}],optOut:[{hide:"#cookie-notice"}]},{name:"cookie-script",vendorUrl:"https://cookie-script.com/",prehideSelectors:["#cookiescript_injected"],detectCmp:[{exists:"#cookiescript_injected"}],detectPopup:[{visible:"#cookiescript_injected"}],optOut:[{if:{exists:"#cookiescript_reject"},then:[{wait:100},{click:"#cookiescript_reject"}],else:[{click:"#cookiescript_manage"},{waitForVisible:".cookiescript_fsd_main"},{waitForThenClick:"#cookiescript_reject"}]}],optIn:[{click:"#cookiescript_accept"}]},{name:"cookieacceptbar",vendorUrl:"https://unknown",cosmetic:!0,prehideSelectors:["#cookieAcceptBar.cookieAcceptBar"],detectCmp:[{exists:"#cookieAcceptBar.cookieAcceptBar"}],detectPopup:[{visible:"#cookieAcceptBar.cookieAcceptBar"}],optIn:[{waitForThenClick:"#cookieAcceptBarConfirm"}],optOut:[{hide:"#cookieAcceptBar.cookieAcceptBar"}]},{name:"cookiealert",intermediate:!1,prehideSelectors:[],runContext:{frame:!0,main:!0},detectCmp:[{exists:".cookie-alert-extended"}],detectPopup:[{visible:".cookie-alert-extended-modal"}],optIn:[{click:"button[data-controller='cookie-alert/extended/button/accept']"},{eval:"EVAL_COOKIEALERT_0"}],optOut:[{click:"a[data-controller='cookie-alert/extended/detail-link']"},{click:".cookie-alert-configuration-input:checked",all:!0,optional:!0},{click:"button[data-controller='cookie-alert/extended/button/configuration']"},{eval:"EVAL_COOKIEALERT_0"}],test:[{eval:"EVAL_COOKIEALERT_2"}]},{name:"cookieconsent2",vendorUrl:"https://www.github.com/orestbida/cookieconsent",comment:"supports v2.x.x of the library",prehideSelectors:["#cc--main"],detectCmp:[{exists:"#cc--main"}],detectPopup:[{visible:"#cm"},{exists:"#s-all-bn"}],optIn:[{waitForThenClick:"#s-all-bn"}],optOut:[{waitForThenClick:"#s-rall-bn"}],test:[{eval:"EVAL_COOKIECONSENT2_TEST"}]},{name:"cookieconsent3",vendorUrl:"https://www.github.com/orestbida/cookieconsent",comment:"supports v3.x.x of the library",prehideSelectors:["#cc-main"],detectCmp:[{exists:"#cc-main"}],detectPopup:[{visible:"#cc-main .cm-wrapper"}],optIn:[{waitForThenClick:".cm__btn[data-role=all]"}],optOut:[{waitForThenClick:".cm__btn[data-role=necessary]"}],test:[{eval:"EVAL_COOKIECONSENT3_TEST"}]},{name:"cookiecuttr",vendorUrl:"https://github.com/cdwharton/cookieCuttr",cosmetic:!1,runContext:{main:!0,frame:!1,urlPattern:""},prehideSelectors:[".cc-cookies"],detectCmp:[{exists:".cc-cookies .cc-cookie-accept"}],detectPopup:[{visible:".cc-cookies .cc-cookie-accept"}],optIn:[{waitForThenClick:".cc-cookies .cc-cookie-accept"}],optOut:[{if:{exists:".cc-cookies .cc-cookie-decline"},then:[{click:".cc-cookies .cc-cookie-decline"}],else:[{hide:".cc-cookies"}]}]},{name:"cookiefirst.com",prehideSelectors:["#cookiefirst-root,.cookiefirst-root,[aria-labelledby=cookie-preference-panel-title]"],detectCmp:[{exists:"#cookiefirst-root,.cookiefirst-root"}],detectPopup:[{visible:"#cookiefirst-root,.cookiefirst-root"}],optIn:[{click:"button[data-cookiefirst-action=accept]"}],optOut:[{if:{exists:"button[data-cookiefirst-action=adjust]"},then:[{click:"button[data-cookiefirst-action=adjust]"},{waitForVisible:"[data-cookiefirst-widget=modal]",timeout:1e3},{eval:"EVAL_COOKIEFIRST_1"},{wait:1e3},{click:"button[data-cookiefirst-action=save]"}],else:[{click:"button[data-cookiefirst-action=reject]"}]}],test:[{eval:"EVAL_COOKIEFIRST_0"}]},{name:"Cookie Information Banner",prehideSelectors:["#cookie-information-template-wrapper"],detectCmp:[{exists:"#cookie-information-template-wrapper"}],detectPopup:[{visible:"#cookie-information-template-wrapper"}],optIn:[{eval:"EVAL_COOKIEINFORMATION_1"}],optOut:[{hide:"#cookie-information-template-wrapper",comment:"some templates don't hide the banner automatically"},{eval:"EVAL_COOKIEINFORMATION_0"}],test:[{eval:"EVAL_COOKIEINFORMATION_2"}]},{name:"cookieyes",prehideSelectors:[".cky-overlay,.cky-consent-container"],detectCmp:[{exists:".cky-consent-container"}],detectPopup:[{visible:".cky-consent-container"}],optIn:[{waitForThenClick:".cky-consent-container [data-cky-tag=accept-button]"}],optOut:[{if:{exists:".cky-consent-container [data-cky-tag=reject-button]"},then:[{waitForThenClick:".cky-consent-container [data-cky-tag=reject-button]"}],else:[{if:{exists:".cky-consent-container [data-cky-tag=settings-button]"},then:[{click:".cky-consent-container [data-cky-tag=settings-button]"},{waitFor:".cky-modal-open input[type=checkbox]"},{click:".cky-modal-open input[type=checkbox]:checked",all:!0,optional:!0},{waitForThenClick:".cky-modal [data-cky-tag=detail-save-button]"}],else:[{hide:".cky-consent-container,.cky-overlay"}]}]}],test:[{eval:"EVAL_COOKIEYES_0"}]},{name:"corona-in-zahlen.de",prehideSelectors:[".cookiealert"],detectCmp:[{exists:".cookiealert"}],detectPopup:[{visible:".cookiealert"}],optOut:[{click:".configurecookies"},{click:".confirmcookies"}],optIn:[{click:".acceptcookies"}]},{name:"crossfit-com",cosmetic:!0,prehideSelectors:['body #modal > div > div[class^="_wrapper_"]'],detectCmp:[{exists:'body #modal > div > div[class^="_wrapper_"]'}],detectPopup:[{visible:'body #modal > div > div[class^="_wrapper_"]'}],optIn:[{click:'button[aria-label="accept cookie policy"]'}],optOut:[{hide:'body #modal > div > div[class^="_wrapper_"]'}]},{name:"csu-landtag-de",runContext:{urlPattern:"^https://(www\\.|)?csu-landtag\\.de"},prehideSelectors:["#cookie-disclaimer"],detectCmp:[{exists:"#cookie-disclaimer"}],detectPopup:[{visible:"#cookie-disclaimer"}],optIn:[{click:"#cookieall"}],optOut:[{click:"#cookiesel"}]},{name:"dailymotion-us",cosmetic:!0,prehideSelectors:['div[class*="CookiePopup__desktopContainer"]:has(div[class*="CookiePopup"])'],detectCmp:[{exists:'div[class*="CookiePopup__desktopContainer"]'}],detectPopup:[{visible:'div[class*="CookiePopup__desktopContainer"]'}],optIn:[{click:'div[class*="CookiePopup__desktopContainer"] > button > span'}],optOut:[{hide:'div[class*="CookiePopup__desktopContainer"]'}]},{name:"dailymotion.com",runContext:{urlPattern:"^https://(www\\.)?dailymotion\\.com/"},prehideSelectors:['div[class*="Overlay__container"]:has(div[class*="TCF2Popup"])'],detectCmp:[{exists:'div[class*="TCF2Popup"]'}],detectPopup:[{visible:'[class*="TCF2Popup"] a[href^="https://www.dailymotion.com/legal/cookiemanagement"]'}],optIn:[{waitForThenClick:'button[class*="TCF2Popup__button"]:not([class*="TCF2Popup__personalize"])'}],optOut:[{waitForThenClick:'button[class*="TCF2ContinueWithoutAcceptingButton"]'}],test:[{eval:"EVAL_DAILYMOTION_0"}]},{name:"deepl.com",prehideSelectors:[".dl_cookieBanner_container"],detectCmp:[{exists:".dl_cookieBanner_container"}],detectPopup:[{visible:".dl_cookieBanner_container"}],optOut:[{click:".dl_cookieBanner--buttonSelected"}],optIn:[{click:".dl_cookieBanner--buttonAll"}]},{name:"delta.com",runContext:{urlPattern:"^https://www\\.delta\\.com/"},cosmetic:!0,prehideSelectors:["ngc-cookie-banner"],detectCmp:[{exists:"div.cookie-footer-container"}],detectPopup:[{visible:"div.cookie-footer-container"}],optIn:[{click:" button.cookie-close-icon"}],optOut:[{hide:"div.cookie-footer-container"}]},{name:"dmgmedia-us",prehideSelectors:["#mol-ads-cmp-iframe, div.mol-ads-cmp > form > div"],detectCmp:[{exists:"div.mol-ads-cmp > form > div"}],detectPopup:[{waitForVisible:"div.mol-ads-cmp > form > div"}],optIn:[{waitForThenClick:"button.mol-ads-cmp--btn-primary"}],optOut:[{waitForThenClick:"div.mol-ads-ccpa--message > u > a"},{waitForVisible:".mol-ads-cmp--modal-dialog"},{waitForThenClick:"a.mol-ads-cmp-footer-privacy"},{waitForThenClick:"button.mol-ads-cmp--btn-secondary"}]},{name:"dmgmedia",prehideSelectors:['[data-project="mol-fe-cmp"]'],detectCmp:[{exists:'[data-project="mol-fe-cmp"]'}],detectPopup:[{visible:'[data-project="mol-fe-cmp"]'}],optIn:[{waitForThenClick:'[data-project="mol-fe-cmp"] button[class*=primary]'}],optOut:[{waitForThenClick:'[data-project="mol-fe-cmp"] button[class*=basic]'},{waitForVisible:'[data-project="mol-fe-cmp"] div[class*="tabContent"]'},{waitForThenClick:'[data-project="mol-fe-cmp"] div[class*="toggle"][class*="enabled"]',all:!0},{waitForThenClick:['[data-project="mol-fe-cmp"] [class*=footer]',"xpath///button[contains(., 'Save & Exit')]"]}]},{name:"dndbeyond",vendorUrl:"https://www.dndbeyond.com/",runContext:{urlPattern:"^https://(www\\.)?dndbeyond\\.com/"},prehideSelectors:["[id^=cookie-consent-banner]"],detectCmp:[{exists:"[id^=cookie-consent-banner]"}],detectPopup:[{visible:"[id^=cookie-consent-banner]"}],optIn:[{waitForThenClick:"#cookie-consent-granted"}],optOut:[{waitForThenClick:"#cookie-consent-denied"}],test:[{eval:"EVAL_DNDBEYOND_TEST"}]},{name:"dpgmedia-nl",prehideSelectors:["#pg-shadow-host"],detectCmp:[{exists:"#pg-shadow-host"}],detectPopup:[{visible:["#pg-shadow-host","#pg-modal"]}],optIn:[{waitForThenClick:["#pg-shadow-host","#pg-accept-btn"]}],optOut:[{waitForThenClick:["#pg-shadow-host","#pg-configure-btn"]},{waitForThenClick:["#pg-shadow-host","#pg-reject-btn"]}]},{name:"Drupal",detectCmp:[{exists:"#drupalorg-crosssite-gdpr"}],detectPopup:[{visible:"#drupalorg-crosssite-gdpr"}],optOut:[{click:".no"}],optIn:[{click:".yes"}]},{name:"WP DSGVO Tools",link:"https://wordpress.org/plugins/shapepress-dsgvo/",prehideSelectors:[".sp-dsgvo"],cosmetic:!0,detectCmp:[{exists:".sp-dsgvo.sp-dsgvo-popup-overlay"}],detectPopup:[{visible:".sp-dsgvo.sp-dsgvo-popup-overlay",check:"any"}],optIn:[{click:".sp-dsgvo-privacy-btn-accept-all",all:!0}],optOut:[{hide:".sp-dsgvo.sp-dsgvo-popup-overlay"}],test:[{eval:"EVAL_DSGVO_0"}]},{name:"dunelm.com",prehideSelectors:["div[data-testid=cookie-consent-modal-backdrop]"],detectCmp:[{exists:"div[data-testid=cookie-consent-message-contents]"}],detectPopup:[{visible:"div[data-testid=cookie-consent-message-contents]"}],optIn:[{click:'[data-testid="cookie-consent-allow-all"]'}],optOut:[{click:"button[data-testid=cookie-consent-adjust-settings]"},{click:"button[data-testid=cookie-consent-preferences-save]"}],test:[{eval:"EVAL_DUNELM_0"}]},{name:"ebay",vendorUrl:"https://ebay.com",cosmetic:!1,runContext:{main:!0,frame:!1,urlPattern:"^https://(www\\.)?ebay\\.([.a-z]+)/"},prehideSelectors:["#gdpr-banner"],detectCmp:[{exists:"#gdpr-banner"}],detectPopup:[{visible:"#gdpr-banner"}],optIn:[{waitForThenClick:"#gdpr-banner-accept"}],optOut:[{waitForThenClick:"#gdpr-banner-decline"}]},{name:"ecosia",vendorUrl:"https://www.ecosia.org/",runContext:{urlPattern:"^https://www\\.ecosia\\.org/"},prehideSelectors:[".cookie-wrapper"],detectCmp:[{exists:".cookie-wrapper > .cookie-notice"}],detectPopup:[{visible:".cookie-wrapper > .cookie-notice"}],optIn:[{waitForThenClick:"[data-test-id=cookie-notice-accept]"}],optOut:[{waitForThenClick:"[data-test-id=cookie-notice-reject]"}]},{name:"Ensighten ensModal",prehideSelectors:[".ensModal"],detectCmp:[{exists:".ensModal"}],detectPopup:[{visible:"#ensModalWrapper[style*=block]"}],optIn:[{waitForThenClick:"#modalAcceptButton"}],optOut:[{wait:500},{visible:"#ensModalWrapper[style*=block]"},{waitForThenClick:".ensCheckbox:checked",all:!0},{waitForThenClick:"#ensSave"}]},{name:"Ensighten ensNotifyBanner",prehideSelectors:["#ensNotifyBanner"],detectCmp:[{exists:"#ensNotifyBanner"}],detectPopup:[{visible:"#ensNotifyBanner[style*=block]"}],optIn:[{waitForThenClick:"#ensCloseBanner"}],optOut:[{wait:500},{visible:"#ensNotifyBanner[style*=block]"},{waitForThenClick:"#ensRejectAll,#rejectAll,#ensRejectBanner,.rejectAll"}]},{name:"espace-personnel.agirc-arrco.fr",runContext:{urlPattern:"^https://espace-personnel\\.agirc-arrco\\.fr/"},prehideSelectors:[".cdk-overlay-container"],detectCmp:[{exists:".cdk-overlay-container app-esaa-cookie-component"}],detectPopup:[{visible:".cdk-overlay-container app-esaa-cookie-component"}],optIn:[{waitForThenClick:".btn-cookie-accepter"}],optOut:[{waitForThenClick:".btn-cookie-refuser"}]},{name:"etsy",prehideSelectors:["#gdpr-single-choice-overlay","#gdpr-privacy-settings"],detectCmp:[{exists:"#gdpr-single-choice-overlay"}],detectPopup:[{visible:"#gdpr-single-choice-overlay"}],optOut:[{click:"button[data-gdpr-open-full-settings]"},{waitForVisible:".gdpr-overlay-body input",timeout:3e3},{wait:1e3},{eval:"EVAL_ETSY_0"},{eval:"EVAL_ETSY_1"}],optIn:[{click:"button[data-gdpr-single-choice-accept]"}]},{name:"eu-cookie-compliance-banner",detectCmp:[{exists:"body.eu-cookie-compliance-popup-open"}],detectPopup:[{exists:"body.eu-cookie-compliance-popup-open"}],optIn:[{click:".agree-button"}],optOut:[{if:{visible:".decline-button,.eu-cookie-compliance-save-preferences-button"},then:[{click:".decline-button,.eu-cookie-compliance-save-preferences-button"}]},{hide:".eu-cookie-compliance-banner-info, #sliding-popup"}],test:[{eval:"EVAL_EU_COOKIE_COMPLIANCE_0"}]},{name:"EU Cookie Law",prehideSelectors:[".pea_cook_wrapper,.pea_cook_more_info_popover"],cosmetic:!0,detectCmp:[{exists:".pea_cook_wrapper"}],detectPopup:[{wait:500},{visible:".pea_cook_wrapper"}],optIn:[{click:"#pea_cook_btn"}],optOut:[{hide:".pea_cook_wrapper"}],test:[{eval:"EVAL_EU_COOKIE_LAW_0"}]},{name:"europa-eu",vendorUrl:"https://ec.europa.eu/",runContext:{urlPattern:"^https://[^/]*europa\\.eu/"},prehideSelectors:["#cookie-consent-banner"],detectCmp:[{exists:".cck-container"}],detectPopup:[{visible:".cck-container"}],optIn:[{waitForThenClick:'.cck-actions-button[href="#accept"]'}],optOut:[{waitForThenClick:'.cck-actions-button[href="#refuse"]',hide:".cck-container"}]},{name:"EZoic",prehideSelectors:["#ez-cookie-dialog-wrapper"],detectCmp:[{exists:"#ez-cookie-dialog-wrapper"}],detectPopup:[{visible:"#ez-cookie-dialog-wrapper"}],optIn:[{click:"#ez-accept-all",optional:!0},{eval:"EVAL_EZOIC_0",optional:!0}],optOut:[{wait:500},{click:"#ez-manage-settings"},{waitFor:"#ez-cookie-dialog input[type=checkbox]"},{click:"#ez-cookie-dialog input[type=checkbox]:checked",all:!0},{click:"#ez-save-settings"}],test:[{eval:"EVAL_EZOIC_1"}]},{name:"facebook",runContext:{urlPattern:"^https://([a-z0-9-]+\\.)?facebook\\.com/"},prehideSelectors:['div[data-testid="cookie-policy-manage-dialog"]'],detectCmp:[{exists:'div[data-testid="cookie-policy-manage-dialog"]'}],detectPopup:[{visible:'div[data-testid="cookie-policy-manage-dialog"]'}],optIn:[{waitForThenClick:'button[data-cookiebanner="accept_button"]'},{waitForVisible:'div[data-testid="cookie-policy-manage-dialog"]',check:"none"}],optOut:[{waitForThenClick:'button[data-cookiebanner="accept_only_essential_button"]'},{waitForVisible:'div[data-testid="cookie-policy-manage-dialog"]',check:"none"}]},{name:"fides",vendorUrl:"https://github.com/ethyca/fides",prehideSelectors:["#fides-overlay"],detectCmp:[{exists:"#fides-overlay #fides-banner"}],detectPopup:[{visible:"#fides-overlay #fides-banner"},{eval:"EVAL_FIDES_DETECT_POPUP"}],optIn:[{waitForThenClick:"#fides-banner .fides-accept-all-button"}],optOut:[{waitForThenClick:"#fides-banner .fides-reject-all-button"}]},{name:"funding-choices",prehideSelectors:[".fc-consent-root,.fc-dialog-container,.fc-dialog-overlay,.fc-dialog-content"],detectCmp:[{exists:".fc-consent-root"}],detectPopup:[{exists:".fc-dialog-container"}],optOut:[{click:".fc-cta-do-not-consent,.fc-cta-manage-options"},{click:".fc-preference-consent:checked,.fc-preference-legitimate-interest:checked",all:!0,optional:!0},{click:".fc-confirm-choices",optional:!0}],optIn:[{click:".fc-cta-consent"}]},{name:"geeks-for-geeks",runContext:{urlPattern:"^https://www\\.geeksforgeeks\\.org/"},cosmetic:!0,prehideSelectors:[".cookie-consent"],detectCmp:[{exists:".cookie-consent"}],detectPopup:[{visible:".cookie-consent"}],optIn:[{click:".cookie-consent button.consent-btn"}],optOut:[{hide:".cookie-consent"}]},{name:"generic-cosmetic",cosmetic:!0,prehideSelectors:["#js-cookie-banner,.js-cookie-banner,.cookie-banner,#cookie-banner"],detectCmp:[{exists:"#js-cookie-banner,.js-cookie-banner,.cookie-banner,#cookie-banner"}],detectPopup:[{visible:"#js-cookie-banner,.js-cookie-banner,.cookie-banner,#cookie-banner"}],optIn:[],optOut:[{hide:"#js-cookie-banner,.js-cookie-banner,.cookie-banner,#cookie-banner"}]},{name:"google-consent-standalone",prehideSelectors:[],detectCmp:[{exists:'a[href^="https://policies.google.com/technologies/cookies"'},{exists:'form[action^="https://consent.google."][action$=".com/save"]'}],detectPopup:[{visible:'a[href^="https://policies.google.com/technologies/cookies"'}],optIn:[{waitForThenClick:'form[action^="https://consent.google."][action$=".com/save"]:has(input[name=set_eom][value=false]) button'}],optOut:[{waitForThenClick:'form[action^="https://consent.google."][action$=".com/save"]:has(input[name=set_eom][value=true]) button'}]},{name:"google.com",prehideSelectors:[".HTjtHe#xe7COe"],detectCmp:[{exists:".HTjtHe#xe7COe"},{exists:'.HTjtHe#xe7COe a[href^="https://policies.google.com/technologies/cookies"]'}],detectPopup:[{visible:".HTjtHe#xe7COe button#W0wltc"}],optIn:[{waitForThenClick:".HTjtHe#xe7COe button#L2AGLb"}],optOut:[{waitForThenClick:".HTjtHe#xe7COe button#W0wltc"}],test:[{eval:"EVAL_GOOGLE_0"}]},{name:"gov.uk",detectCmp:[{exists:"#global-cookie-message"}],detectPopup:[{exists:"#global-cookie-message"}],optIn:[{click:"button[data-accept-cookies=true]"}],optOut:[{click:"button[data-reject-cookies=true],#reject-cookies"},{click:"button[data-hide-cookie-banner=true],#hide-cookie-decision"}]},{name:"hashicorp",vendorUrl:"https://hashicorp.com/",runContext:{urlPattern:"^https://[^.]*\\.hashicorp\\.com/"},prehideSelectors:["[data-testid=consent-banner]"],detectCmp:[{exists:"[data-testid=consent-banner]"}],detectPopup:[{visible:"[data-testid=consent-banner]"}],optIn:[{waitForThenClick:"[data-testid=accept]"}],optOut:[{waitForThenClick:"[data-testid=manage-preferences]"},{waitForThenClick:"[data-testid=consent-mgr-dialog] [data-ga-button=save-preferences]"}]},{name:"healthline-media",prehideSelectors:["#modal-host > div.no-hash > div.window-wrapper"],detectCmp:[{exists:"#modal-host > div.no-hash > div.window-wrapper, div[data-testid=qualtrics-container]"}],detectPopup:[{exists:"#modal-host > div.no-hash > div.window-wrapper, div[data-testid=qualtrics-container]"}],optIn:[{click:"#modal-host > div.no-hash > div.window-wrapper > div:last-child button"}],optOut:[{if:{exists:'#modal-host > div.no-hash > div.window-wrapper > div:last-child a[href="/privacy-settings"]'},then:[{click:'#modal-host > div.no-hash > div.window-wrapper > div:last-child a[href="/privacy-settings"]'}],else:[{waitForVisible:"div#__next"},{click:"#__next div:nth-child(1) > button:first-child"}]}]},{name:"hema",prehideSelectors:[".cookie-modal"],detectCmp:[{visible:".cookie-modal .cookie-accept-btn"}],detectPopup:[{visible:".cookie-modal .cookie-accept-btn"}],optIn:[{waitForThenClick:".cookie-modal .cookie-accept-btn"}],optOut:[{waitForThenClick:".cookie-modal .js-cookie-reject-btn"}],test:[{eval:"EVAL_HEMA_TEST_0"}]},{name:"hetzner.com",runContext:{urlPattern:"^https://www\\.hetzner\\.com/"},prehideSelectors:["#CookieConsent"],detectCmp:[{exists:"#CookieConsent"}],detectPopup:[{visible:"#CookieConsent"}],optIn:[{click:"#CookieConsentGiven"}],optOut:[{click:"#CookieConsentDeclined"}]},{name:"hl.co.uk",prehideSelectors:[".cookieModalContent","#cookie-banner-overlay"],detectCmp:[{exists:"#cookie-banner-overlay"}],detectPopup:[{exists:"#cookie-banner-overlay"}],optIn:[{click:"#acceptCookieButton"}],optOut:[{click:"#manageCookie"},{hide:".cookieSettingsModal"},{waitFor:"#AOCookieToggle"},{click:"#AOCookieToggle[aria-pressed=true]",optional:!0},{waitFor:"#TPCookieToggle"},{click:"#TPCookieToggle[aria-pressed=true]",optional:!0},{click:"#updateCookieButton"}]},{name:"holidaymedia",vendorUrl:"https://holidaymedia.nl/",prehideSelectors:["dialog[data-cookie-consent]"],detectCmp:[{exists:"dialog[data-cookie-consent]"}],detectPopup:[{visible:"dialog[data-cookie-consent]"}],optIn:[{waitForThenClick:"button.cookie-consent__button--accept-all"}],optOut:[{waitForThenClick:'a[data-cookie-accept="functional"]',timeout:2e3}]},{name:"hu-manity",vendorUrl:"https://hu-manity.co/",prehideSelectors:["#hu.hu-wrapper"],detectCmp:[{exists:"#hu.hu-visible"}],detectPopup:[{visible:"#hu.hu-visible"}],optIn:[{waitForThenClick:"[data-hu-action=cookies-notice-consent-choices-3]"},{waitForThenClick:"#hu-cookies-save"}],optOut:[{waitForThenClick:"#hu-cookies-save"}]},{name:"hubspot",detectCmp:[{exists:"#hs-eu-cookie-confirmation"}],detectPopup:[{visible:"#hs-eu-cookie-confirmation"}],optIn:[{click:"#hs-eu-confirmation-button"}],optOut:[{click:"#hs-eu-decline-button"}]},{name:"indeed.com",cosmetic:!0,prehideSelectors:["#CookiePrivacyNotice"],detectCmp:[{exists:"#CookiePrivacyNotice"}],detectPopup:[{visible:"#CookiePrivacyNotice"}],optIn:[{click:"#CookiePrivacyNotice button[data-gnav-element-name=CookiePrivacyNoticeOk]"}],optOut:[{hide:"#CookiePrivacyNotice"}]},{name:"ing.de",runContext:{urlPattern:"^https://www\\.ing\\.de/"},cosmetic:!0,prehideSelectors:['div[slot="backdrop"]'],detectCmp:[{exists:'[data-tag-name="ing-cc-dialog-frame"]'}],detectPopup:[{visible:'[data-tag-name="ing-cc-dialog-frame"]'}],optIn:[{click:['[data-tag-name="ing-cc-dialog-level0"]','[data-tag-name="ing-cc-button"][class*="accept"]']}],optOut:[{click:['[data-tag-name="ing-cc-dialog-level0"]','[data-tag-name="ing-cc-button"][class*="more"]']}]},{name:"instagram",vendorUrl:"https://instagram.com",runContext:{urlPattern:"^https://www\\.instagram\\.com/"},prehideSelectors:[".x78zum5.xdt5ytf.xg6iff7.x1n2onr6:has(._a9--)"],detectCmp:[{exists:".x1qjc9v5.x9f619.x78zum5.xdt5ytf.x1iyjqo2.xl56j7k"}],detectPopup:[{visible:".x1qjc9v5.x9f619.x78zum5.xdt5ytf.x1iyjqo2.xl56j7k"}],optIn:[{waitForThenClick:"._a9--._a9_0"}],optOut:[{waitForThenClick:"._a9--._a9_1"},{wait:2e3}]},{name:"ionos.de",prehideSelectors:[".privacy-consent--backdrop",".privacy-consent--modal"],detectCmp:[{exists:".privacy-consent--modal"}],detectPopup:[{visible:".privacy-consent--modal"}],optIn:[{click:"#selectAll"}],optOut:[{click:".footer-config-link"},{click:"#confirmSelection"}]},{name:"itopvpn.com",cosmetic:!0,prehideSelectors:[".pop-cookie"],detectCmp:[{exists:".pop-cookie"}],detectPopup:[{exists:".pop-cookie"}],optIn:[{click:"#_pcookie"}],optOut:[{hide:".pop-cookie"}]},{name:"iubenda",prehideSelectors:["#iubenda-cs-banner"],detectCmp:[{exists:"#iubenda-cs-banner"}],detectPopup:[{visible:".iubenda-cs-accept-btn"}],optIn:[{waitForThenClick:".iubenda-cs-accept-btn"}],optOut:[{waitForThenClick:".iubenda-cs-customize-btn"},{eval:"EVAL_IUBENDA_0"},{waitForThenClick:"#iubFooterBtn"}],test:[{eval:"EVAL_IUBENDA_1"}]},{name:"iWink",prehideSelectors:["body.cookies-request #cookie-bar"],detectCmp:[{exists:"body.cookies-request #cookie-bar"}],detectPopup:[{visible:"body.cookies-request #cookie-bar"}],optIn:[{waitForThenClick:"body.cookies-request #cookie-bar .allow-cookies"}],optOut:[{waitForThenClick:"body.cookies-request #cookie-bar .disallow-cookies"}],test:[{eval:"EVAL_IWINK_TEST"}]},{name:"jdsports",vendorUrl:"https://www.jdsports.co.uk/",runContext:{urlPattern:"^https://(www|m)\\.jdsports\\."},prehideSelectors:[".miniConsent,#PrivacyPolicyBanner"],detectCmp:[{exists:".miniConsent,#PrivacyPolicyBanner"}],detectPopup:[{visible:".miniConsent,#PrivacyPolicyBanner"}],optIn:[{waitForThenClick:".miniConsent .accept-all-cookies"}],optOut:[{if:{exists:"#PrivacyPolicyBanner"},then:[{hide:"#PrivacyPolicyBanner"}],else:[{waitForThenClick:"#cookie-settings"},{waitForThenClick:"#reject-all-cookies"}]}]},{name:"johnlewis.com",prehideSelectors:["div[class^=pecr-cookie-banner-]"],detectCmp:[{exists:"div[class^=pecr-cookie-banner-]"}],detectPopup:[{exists:"div[class^=pecr-cookie-banner-]"}],optOut:[{click:"button[data-test^=manage-cookies]"},{wait:"500"},{click:"label[data-test^=toggle][class*=checked]:not([class*=disabled])",all:!0,optional:!0},{click:"button[data-test=save-preferences]"}],optIn:[{click:"button[data-test=allow-all]"}]},{name:"jquery.cookieBar",vendorUrl:"https://github.com/kovarp/jquery.cookieBar",prehideSelectors:[".cookie-bar"],cosmetic:!0,detectCmp:[{exists:".cookie-bar .cookie-bar__message,.cookie-bar .cookie-bar__buttons"}],detectPopup:[{visible:".cookie-bar .cookie-bar__message,.cookie-bar .cookie-bar__buttons",check:"any"}],optIn:[{click:".cookie-bar .cookie-bar__btn"}],optOut:[{hide:".cookie-bar"}],test:[{visible:".cookie-bar .cookie-bar__message,.cookie-bar .cookie-bar__buttons",check:"none"},{eval:"EVAL_JQUERY_COOKIEBAR_0"}]},{name:"justwatch.com",prehideSelectors:[".consent-banner"],detectCmp:[{exists:".consent-banner .consent-banner__actions"}],detectPopup:[{visible:".consent-banner .consent-banner__actions"}],optIn:[{click:".consent-banner__actions button.basic-button.primary"}],optOut:[{click:".consent-banner__actions button.basic-button.secondary"},{waitForThenClick:".consent-modal__footer button.basic-button.secondary"},{waitForThenClick:".consent-modal ion-content > div > a:nth-child(9)"},{click:"label.consent-switch input[type=checkbox]:checked",all:!0,optional:!0},{waitForVisible:".consent-modal__footer button.basic-button.primary"},{click:".consent-modal__footer button.basic-button.primary"}]},{name:"ketch",vendorUrl:"https://www.ketch.com",runContext:{frame:!1,main:!0},intermediate:!1,prehideSelectors:["#lanyard_root div[role='dialog']"],detectCmp:[{exists:"#lanyard_root div[role='dialog']"}],detectPopup:[{visible:"#lanyard_root div[role='dialog']"}],optIn:[{if:{exists:"#lanyard_root button[class='confirmButton']"},then:[{waitForThenClick:"#lanyard_root div[class*=buttons] > :nth-child(2)"},{click:"#lanyard_root button[class='confirmButton']"}],else:[{waitForThenClick:"#lanyard_root div[class*=buttons] > :nth-child(2)"}]}],optOut:[{if:{exists:"#lanyard_root [aria-describedby=banner-description]"},then:[{waitForThenClick:"#lanyard_root div[class*=buttons] > button[class*=secondaryButton], #lanyard_root button[class*=buttons-secondary]",comment:"can be either settings or reject button"}]},{waitFor:"#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description], #ketch-preferences",timeout:1e3,optional:!0},{if:{exists:"#lanyard_root [aria-describedby=preference-description],#lanyard_root [aria-describedby=modal-description], #ketch-preferences"},then:[{waitForThenClick:"#lanyard_root button[class*=rejectButton], #lanyard_root button[class*=rejectAllButton]"},{click:"#lanyard_root button[class*=confirmButton],#lanyard_root div[class*=actions_] > button:nth-child(1), #lanyard_root button[class*=actionButton]"}]}],test:[{eval:"EVAL_KETCH_TEST"}]},{name:"kleinanzeigen-de",runContext:{urlPattern:"^https?://(www\\.)?kleinanzeigen\\.de"},prehideSelectors:["#gdpr-banner-container"],detectCmp:[{any:[{exists:"#gdpr-banner-container #gdpr-banner [data-testid=gdpr-banner-cmp-button]"},{exists:"#ConsentManagementPage"}]}],detectPopup:[{any:[{visible:"#gdpr-banner-container #gdpr-banner [data-testid=gdpr-banner-cmp-button]"},{visible:"#ConsentManagementPage"}]}],optIn:[{if:{exists:"#gdpr-banner-container #gdpr-banner"},then:[{click:"#gdpr-banner-container #gdpr-banner [data-testid=gdpr-banner-accept]"}],else:[{click:"#ConsentManagementPage .Button-primary"}]}],optOut:[{if:{exists:"#gdpr-banner-container #gdpr-banner"},then:[{click:"#gdpr-banner-container #gdpr-banner [data-testid=gdpr-banner-cmp-button]"}],else:[{click:"#ConsentManagementPage .Button-secondary"}]}]},{name:"lightbox",prehideSelectors:[".darken-layer.open,.lightbox.lightbox--cookie-consent"],detectCmp:[{exists:"body.cookie-consent-is-active div.lightbox--cookie-consent > div.lightbox__content > div.cookie-consent[data-jsb]"}],detectPopup:[{visible:"body.cookie-consent-is-active div.lightbox--cookie-consent > div.lightbox__content > div.cookie-consent[data-jsb]"}],optOut:[{click:".cookie-consent__footer > button[type='submit']:not([data-button='selectAll'])"}],optIn:[{click:".cookie-consent__footer > button[type='submit'][data-button='selectAll']"}]},{name:"lineagrafica",vendorUrl:"https://addons.prestashop.com/en/legal/8734-eu-cookie-law-gdpr-banner-blocker.html",cosmetic:!0,prehideSelectors:["#lgcookieslaw_banner,#lgcookieslaw_modal,.lgcookieslaw-overlay"],detectCmp:[{exists:"#lgcookieslaw_banner,#lgcookieslaw_modal,.lgcookieslaw-overlay"}],detectPopup:[{exists:"#lgcookieslaw_banner,#lgcookieslaw_modal,.lgcookieslaw-overlay"}],optIn:[{waitForThenClick:"#lgcookieslaw_accept"}],optOut:[{hide:"#lgcookieslaw_banner,#lgcookieslaw_modal,.lgcookieslaw-overlay"}]},{name:"linkedin.com",prehideSelectors:[".artdeco-global-alert[type=COOKIE_CONSENT]"],detectCmp:[{exists:".artdeco-global-alert[type=COOKIE_CONSENT]"}],detectPopup:[{visible:".artdeco-global-alert[type=COOKIE_CONSENT]"}],optIn:[{waitForVisible:".artdeco-global-alert[type=COOKIE_CONSENT] button[action-type=ACCEPT]"},{wait:500},{waitForThenClick:".artdeco-global-alert[type=COOKIE_CONSENT] button[action-type=ACCEPT]"}],optOut:[{waitForVisible:".artdeco-global-alert[type=COOKIE_CONSENT] button[action-type=DENY]"},{wait:500},{waitForThenClick:".artdeco-global-alert[type=COOKIE_CONSENT] button[action-type=DENY]"}],test:[{waitForVisible:".artdeco-global-alert[type=COOKIE_CONSENT]",check:"none"}]},{name:"livejasmin",vendorUrl:"https://www.livejasmin.com/",runContext:{urlPattern:"^https://(m|www)\\.livejasmin\\.com/"},prehideSelectors:["#consent_modal"],detectCmp:[{exists:"#consent_modal"}],detectPopup:[{visible:"#consent_modal"}],optIn:[{waitForThenClick:"#consent_modal button[data-testid=ButtonStyledButton]:first-of-type"}],optOut:[{waitForThenClick:"#consent_modal button[data-testid=ButtonStyledButton]:nth-of-type(2)"},{waitForVisible:"[data-testid=PrivacyPreferenceCenterWithConsentCookieContent]"},{click:"[data-testid=PrivacyPreferenceCenterWithConsentCookieContent] input[data-testid=PrivacyPreferenceCenterWithConsentCookieSwitch]:checked",optional:!0,all:!0},{waitForThenClick:"[data-testid=PrivacyPreferenceCenterWithConsentCookieContent] button[data-testid=ButtonStyledButton]:last-child"}]},{name:"macpaw.com",cosmetic:!0,prehideSelectors:['div[data-banner="cookies"]'],detectCmp:[{exists:'div[data-banner="cookies"]'}],detectPopup:[{exists:'div[data-banner="cookies"]'}],optIn:[{click:'button[data-banner-close="cookies"]'}],optOut:[{hide:'div[data-banner="cookies"]'}]},{name:"marksandspencer.com",cosmetic:!0,detectCmp:[{exists:".navigation-cookiebbanner"}],detectPopup:[{visible:".navigation-cookiebbanner"}],optOut:[{hide:".navigation-cookiebbanner"}],optIn:[{click:".navigation-cookiebbanner__submit"}]},{name:"mediamarkt.de",prehideSelectors:["div[aria-labelledby=pwa-consent-layer-title]","div[class^=StyledConsentLayerWrapper-]"],detectCmp:[{exists:"div[aria-labelledby^=pwa-consent-layer-title]"}],detectPopup:[{exists:"div[aria-labelledby^=pwa-consent-layer-title]"}],optOut:[{click:"button[data-test^=pwa-consent-layer-deny-all]"}],optIn:[{click:"button[data-test^=pwa-consent-layer-accept-all"}]},{name:"Mediavine",prehideSelectors:['[data-name="mediavine-gdpr-cmp"]'],detectCmp:[{exists:'[data-name="mediavine-gdpr-cmp"]'}],detectPopup:[{wait:500},{visible:'[data-name="mediavine-gdpr-cmp"]'}],optIn:[{waitForThenClick:'[data-name="mediavine-gdpr-cmp"] [format="primary"]'}],optOut:[{waitForThenClick:'[data-name="mediavine-gdpr-cmp"] [data-view="manageSettings"]'},{waitFor:'[data-name="mediavine-gdpr-cmp"] input[type=checkbox]'},{eval:"EVAL_MEDIAVINE_0",optional:!0},{click:'[data-name="mediavine-gdpr-cmp"] [format="secondary"]'}]},{name:"microsoft.com",prehideSelectors:["#wcpConsentBannerCtrl"],detectCmp:[{exists:"#wcpConsentBannerCtrl"}],detectPopup:[{exists:"#wcpConsentBannerCtrl"}],optOut:[{eval:"EVAL_MICROSOFT_0"}],optIn:[{eval:"EVAL_MICROSOFT_1"}],test:[{eval:"EVAL_MICROSOFT_2"}]},{name:"midway-usa",runContext:{urlPattern:"^https://www\\.midwayusa\\.com/"},cosmetic:!0,prehideSelectors:["#cookie-container"],detectCmp:[{exists:['div[aria-label="Cookie Policy Banner"]']}],detectPopup:[{visible:"#cookie-container"}],optIn:[{click:"button#cookie-btn"}],optOut:[{hide:'div[aria-label="Cookie Policy Banner"]'}]},{name:"moneysavingexpert.com",detectCmp:[{exists:"dialog[data-testid=accept-our-cookies-dialog]"}],detectPopup:[{visible:"dialog[data-testid=accept-our-cookies-dialog]"}],optIn:[{click:"#banner-accept"}],optOut:[{click:"#banner-manage"},{click:"#pc-confirm"}]},{name:"monzo.com",prehideSelectors:[".cookie-alert, cookie-alert__content"],detectCmp:[{exists:'div.cookie-alert[role="dialog"]'},{exists:'a[href*="monzo"]'}],detectPopup:[{visible:".cookie-alert__content"}],optIn:[{click:".js-accept-cookie-policy"}],optOut:[{click:".js-decline-cookie-policy"}]},{name:"Moove",prehideSelectors:["#moove_gdpr_cookie_info_bar"],detectCmp:[{exists:"#moove_gdpr_cookie_info_bar"}],detectPopup:[{visible:"#moove_gdpr_cookie_info_bar:not(.moove-gdpr-info-bar-hidden)"}],optIn:[{waitForThenClick:".moove-gdpr-infobar-allow-all"}],optOut:[{if:{exists:"#moove_gdpr_cookie_info_bar .change-settings-button"},then:[{click:"#moove_gdpr_cookie_info_bar .change-settings-button"},{waitForVisible:"#moove_gdpr_cookie_modal"},{eval:"EVAL_MOOVE_0"},{click:".moove-gdpr-modal-save-settings"}],else:[{hide:"#moove_gdpr_cookie_info_bar"}]}],test:[{visible:"#moove_gdpr_cookie_info_bar",check:"none"}]},{name:"national-lottery.co.uk",detectCmp:[{exists:".cuk_cookie_consent"}],detectPopup:[{visible:".cuk_cookie_consent",check:"any"}],optOut:[{click:".cuk_cookie_consent_manage_pref"},{click:".cuk_cookie_consent_save_pref"},{click:".cuk_cookie_consent_close"}],optIn:[{click:".cuk_cookie_consent_accept_all"}]},{name:"nba.com",runContext:{urlPattern:"^https://(www\\.)?nba.com/"},cosmetic:!0,prehideSelectors:["#onetrust-banner-sdk"],detectCmp:[{exists:"#onetrust-banner-sdk"}],detectPopup:[{visible:"#onetrust-banner-sdk"}],optIn:[{click:"#onetrust-accept-btn-handler"}],optOut:[{hide:"#onetrust-banner-sdk"}]},{name:"netbeat.de",runContext:{urlPattern:"^https://(www\\.)?netbeat\\.de/"},prehideSelectors:["div#cookieWarning"],detectCmp:[{exists:"div#cookieWarning"}],detectPopup:[{visible:"div#cookieWarning"}],optIn:[{waitForThenClick:"a#btnCookiesAcceptAll"}],optOut:[{waitForThenClick:"a#btnCookiesDenyAll"}]},{name:"netflix.de",detectCmp:[{exists:"#cookie-disclosure"}],detectPopup:[{visible:".cookie-disclosure-message",check:"any"}],optIn:[{click:".btn-accept"}],optOut:[{hide:"#cookie-disclosure"},{click:".btn-reject"}]},{name:"nhs.uk",prehideSelectors:["#nhsuk-cookie-banner"],detectCmp:[{exists:"#nhsuk-cookie-banner"}],detectPopup:[{exists:"#nhsuk-cookie-banner"}],optOut:[{click:"#nhsuk-cookie-banner__link_accept"}],optIn:[{click:"#nhsuk-cookie-banner__link_accept_analytics"}]},{name:"notice-cookie",prehideSelectors:[".button--notice"],cosmetic:!0,detectCmp:[{exists:".notice--cookie"}],detectPopup:[{visible:".notice--cookie"}],optIn:[{click:".button--notice"}],optOut:[{hide:".notice--cookie"}]},{name:"nrk.no",cosmetic:!0,prehideSelectors:[".nrk-masthead__info-banner--cookie"],detectCmp:[{exists:".nrk-masthead__info-banner--cookie"}],detectPopup:[{exists:".nrk-masthead__info-banner--cookie"}],optIn:[{click:"div.nrk-masthead__info-banner--cookie button > span:has(+ svg.nrk-close)"}],optOut:[{hide:".nrk-masthead__info-banner--cookie"}]},{name:"obi.de",prehideSelectors:[".disc-cp--active"],detectCmp:[{exists:".disc-cp-modal__modal"}],detectPopup:[{visible:".disc-cp-modal__modal"}],optIn:[{click:".js-disc-cp-accept-all"}],optOut:[{click:".js-disc-cp-deny-all"}]},{name:"om",vendorUrl:"https://olli-machts.de/en/extension/cookie-manager",prehideSelectors:[".tx-om-cookie-consent"],detectCmp:[{exists:".tx-om-cookie-consent .active[data-omcookie-panel]"}],detectPopup:[{exists:".tx-om-cookie-consent .active[data-omcookie-panel]"}],optIn:[{waitForThenClick:"[data-omcookie-panel-save=all]"}],optOut:[{if:{exists:"[data-omcookie-panel-save=min]"},then:[{waitForThenClick:"[data-omcookie-panel-save=min]"}],else:[{click:"input[data-omcookie-panel-grp]:checked:not(:disabled)",all:!0,optional:!0},{waitForThenClick:"[data-omcookie-panel-save=save]"}]}]},{name:"onlyFans.com",runContext:{urlPattern:"^https://onlyfans\\.com/"},prehideSelectors:["div.b-cookies-informer"],detectCmp:[{exists:"div.b-cookies-informer"}],detectPopup:[{exists:"div.b-cookies-informer"}],optIn:[{click:"div.b-cookies-informer__nav > button:nth-child(2)"}],optOut:[{click:"div.b-cookies-informer__nav > button:nth-child(1)"},{if:{exists:"div.b-cookies-informer__switchers"},then:[{click:"div.b-cookies-informer__switchers input:not([disabled])",all:!0},{click:"div.b-cookies-informer__nav > button"}]}]},{name:"openli",vendorUrl:"https://openli.com",prehideSelectors:[".legalmonster-cleanslate"],detectCmp:[{exists:".legalmonster-cleanslate"}],detectPopup:[{visible:".legalmonster-cleanslate #lm-cookie-wall-container",check:"any"}],optIn:[{waitForThenClick:"#lm-accept-all"}],optOut:[{waitForThenClick:"#lm-accept-necessary"}]},{name:"opera.com",vendorUrl:"https://unknown",cosmetic:!1,runContext:{main:!0,frame:!1},intermediate:!1,prehideSelectors:[],detectCmp:[{exists:"#cookie-consent .manage-cookies__btn"}],detectPopup:[{visible:"#cookie-consent .cookie-basic-consent__btn"}],optIn:[{waitForThenClick:"#cookie-consent .cookie-basic-consent__btn"}],optOut:[{waitForThenClick:"#cookie-consent .manage-cookies__btn"},{waitForThenClick:"#cookie-consent .active.marketing_option_switch.cookie-consent__switch",all:!0},{waitForThenClick:"#cookie-consent .cookie-selection__btn"}],test:[{eval:"EVAL_OPERA_0"}]},{name:"osano",prehideSelectors:[".osano-cm-window,.osano-cm-dialog"],detectCmp:[{exists:".osano-cm-window"}],detectPopup:[{visible:".osano-cm-dialog"}],optIn:[{click:".osano-cm-accept-all",optional:!0}],optOut:[{waitForThenClick:".osano-cm-denyAll"}]},{name:"otto.de",prehideSelectors:[".cookieBanner--visibility"],detectCmp:[{exists:".cookieBanner--visibility"}],detectPopup:[{visible:".cookieBanner__wrapper"}],optIn:[{click:".js_cookieBannerPermissionButton"}],optOut:[{click:".js_cookieBannerProhibitionButton"}]},{name:"ourworldindata",vendorUrl:"https://ourworldindata.org/",runContext:{urlPattern:"^https://ourworldindata\\.org/"},prehideSelectors:[".cookie-manager"],detectCmp:[{exists:".cookie-manager"}],detectPopup:[{visible:".cookie-manager .cookie-notice.open"}],optIn:[{waitForThenClick:".cookie-notice [data-test=accept]"}],optOut:[{waitForThenClick:".cookie-notice [data-test=reject]"}]},{name:"pabcogypsum",vendorUrl:"https://unknown",prehideSelectors:[".js-cookie-notice:has(#cookie_settings-form)"],detectCmp:[{exists:".js-cookie-notice #cookie_settings-form"}],detectPopup:[{visible:".js-cookie-notice #cookie_settings-form"}],optIn:[{waitForThenClick:".js-cookie-notice button[value=allow]"}],optOut:[{waitForThenClick:".js-cookie-notice button[value=disable]"}]},{name:"paypal-us",prehideSelectors:["#ccpaCookieContent_wrapper, article.ppvx_modal--overpanel"],detectCmp:[{exists:"#ccpaCookieBanner, .privacy-sheet-content"}],detectPopup:[{exists:"#ccpaCookieBanner, .privacy-sheet-content"}],optIn:[{click:"#acceptAllButton"}],optOut:[{if:{exists:"a#manageCookiesLink"},then:[{click:"a#manageCookiesLink"}],else:[{waitForVisible:".privacy-sheet-content #formContent"},{click:"#formContent .cookiepref-11m2iee-checkbox_base input:checked",all:!0,optional:!0},{click:".confirmCookie #submitCookiesBtn"}]}]},{name:"paypal.com",prehideSelectors:["#gdprCookieBanner"],detectCmp:[{exists:"#gdprCookieBanner"}],detectPopup:[{visible:"#gdprCookieContent_wrapper"}],optIn:[{click:"#acceptAllButton"}],optOut:[{wait:200},{click:".gdprCookieBanner_decline-button"}],test:[{wait:500},{eval:"EVAL_PAYPAL_0"}]},{name:"pinetools.com",cosmetic:!0,prehideSelectors:["#aviso_cookies"],detectCmp:[{exists:"#aviso_cookies"}],detectPopup:[{exists:".lang_en #aviso_cookies"}],optIn:[{click:"#aviso_cookies .a_boton_cerrar"}],optOut:[{hide:"#aviso_cookies"}]},{name:"pmc",cosmetic:!0,prehideSelectors:["#pmc-pp-tou--notice"],detectCmp:[{exists:"#pmc-pp-tou--notice"}],detectPopup:[{visible:"#pmc-pp-tou--notice"}],optIn:[{click:"span.pmc-pp-tou--notice-close-btn"}],optOut:[{hide:"#pmc-pp-tou--notice"}]},{name:"pornhub.com",runContext:{urlPattern:"^https://(www\\.)?pornhub\\.com/"},cosmetic:!0,prehideSelectors:[".cookiesBanner"],detectCmp:[{exists:".cookiesBanner"}],detectPopup:[{visible:".cookiesBanner"}],optIn:[{click:".cookiesBanner .okButton"}],optOut:[{hide:".cookiesBanner"}]},{name:"pornpics.com",cosmetic:!0,prehideSelectors:["#cookie-contract"],detectCmp:[{exists:"#cookie-contract"}],detectPopup:[{visible:"#cookie-contract"}],optIn:[{click:"#cookie-contract .icon-cross"}],optOut:[{hide:"#cookie-contract"}]},{name:"PrimeBox CookieBar",prehideSelectors:["#cookie-bar"],detectCmp:[{exists:"#cookie-bar .cb-enable,#cookie-bar .cb-disable,#cookie-bar .cb-policy"}],detectPopup:[{visible:"#cookie-bar .cb-enable,#cookie-bar .cb-disable,#cookie-bar .cb-policy",check:"any"}],optIn:[{waitForThenClick:"#cookie-bar .cb-enable"}],optOut:[{click:"#cookie-bar .cb-disable",optional:!0},{hide:"#cookie-bar"}],test:[{eval:"EVAL_PRIMEBOX_0"}]},{name:"privacymanager.io",prehideSelectors:["#gdpr-consent-tool-wrapper",'iframe[src^="https://cmp-consent-tool.privacymanager.io"]'],runContext:{urlPattern:"^https://cmp-consent-tool\\.privacymanager\\.io/",main:!1,frame:!0},detectCmp:[{exists:"button#save"}],detectPopup:[{visible:"button#save"}],optIn:[{click:"button#save"}],optOut:[{if:{exists:"#denyAll"},then:[{click:"#denyAll"},{waitForThenClick:".okButton"}],else:[{waitForThenClick:"#manageSettings"},{waitFor:".purposes-overview-list"},{waitFor:"button#saveAndExit"},{click:"span[role=checkbox][aria-checked=true]",all:!0,optional:!0},{click:"button#saveAndExit"}]}]},{name:"productz.com",vendorUrl:"https://productz.com/",runContext:{urlPattern:"^https://productz\\.com/"},prehideSelectors:[],detectCmp:[{exists:".c-modal.is-active"}],detectPopup:[{visible:".c-modal.is-active"}],optIn:[{waitForThenClick:".c-modal.is-active .is-accept"}],optOut:[{waitForThenClick:".c-modal.is-active .is-dismiss"}]},{name:"pubtech",prehideSelectors:["#pubtech-cmp"],detectCmp:[{exists:"#pubtech-cmp"}],detectPopup:[{visible:"#pubtech-cmp #pt-actions"}],optIn:[{if:{exists:"#pt-accept-all"},then:[{click:"#pubtech-cmp #pt-actions #pt-accept-all"}],else:[{click:"#pubtech-cmp #pt-actions button:nth-of-type(2)"}]}],optOut:[{click:"#pubtech-cmp #pt-close"}],test:[{eval:"EVAL_PUBTECH_0"}]},{name:"quantcast",prehideSelectors:["#qc-cmp2-main,#qc-cmp2-container"],detectCmp:[{exists:"#qc-cmp2-container"}],detectPopup:[{visible:"#qc-cmp2-ui"}],optOut:[{click:'.qc-cmp2-summary-buttons > button[mode="secondary"]'},{waitFor:"#qc-cmp2-ui"},{click:'.qc-cmp2-toggle-switch > button[aria-checked="true"]',all:!0,optional:!0},{click:'.qc-cmp2-main button[aria-label="REJECT ALL"]',optional:!0},{waitForThenClick:'.qc-cmp2-main button[aria-label="SAVE & EXIT"],.qc-cmp2-buttons-desktop > button[mode="primary"]',timeout:5e3}],optIn:[{click:'.qc-cmp2-summary-buttons > button[mode="primary"]'}]},{name:"reddit.com",runContext:{urlPattern:"^https://www\\.reddit\\.com/"},prehideSelectors:["[bundlename=reddit_cookie_banner]"],detectCmp:[{exists:"reddit-cookie-banner"}],detectPopup:[{visible:"reddit-cookie-banner"}],optIn:[{waitForThenClick:["reddit-cookie-banner","#accept-all-cookies-button > button"]}],optOut:[{waitForThenClick:["reddit-cookie-banner","#reject-nonessential-cookies-button > button"]}],test:[{eval:"EVAL_REDDIT_0"}]},{name:"roblox",vendorUrl:"https://roblox.com",cosmetic:!1,runContext:{main:!0,frame:!1,urlPattern:"^https://(www\\.)?roblox\\.com/"},prehideSelectors:[],detectCmp:[{exists:".cookie-banner-wrapper"}],detectPopup:[{visible:".cookie-banner-wrapper .cookie-banner"}],optIn:[{waitForThenClick:".cookie-banner-wrapper button.btn-cta-lg"}],optOut:[{waitForThenClick:".cookie-banner-wrapper button.btn-secondary-lg"}],test:[{eval:"EVAL_ROBLOX_TEST"}]},{name:"rog-forum.asus.com",runContext:{urlPattern:"^https://rog-forum\\.asus\\.com/"},prehideSelectors:["#cookie-policy-info"],detectCmp:[{exists:"#cookie-policy-info"}],detectPopup:[{visible:"#cookie-policy-info"}],optIn:[{click:'div.cookie-btn-box > div[aria-label="Accept"]'}],optOut:[{click:'div.cookie-btn-box > div[aria-label="Reject"]'},{waitForThenClick:'.cookie-policy-lightbox-bottom > div[aria-label="Save Settings"]'}]},{name:"roofingmegastore.co.uk",runContext:{urlPattern:"^https://(www\\.)?roofingmegastore\\.co\\.uk"},prehideSelectors:["#m-cookienotice"],detectCmp:[{exists:"#m-cookienotice"}],detectPopup:[{visible:"#m-cookienotice"}],optIn:[{click:"#accept-cookies"}],optOut:[{click:"#manage-cookies"},{waitForThenClick:"#accept-selected"}]},{name:"samsung.com",runContext:{urlPattern:"^https://www\\.samsung\\.com/"},cosmetic:!0,prehideSelectors:["div.cookie-bar"],detectCmp:[{exists:"div.cookie-bar"}],detectPopup:[{visible:"div.cookie-bar"}],optIn:[{click:"div.cookie-bar__manage > a"}],optOut:[{hide:"div.cookie-bar"}]},{name:"setapp.com",vendorUrl:"https://setapp.com/",cosmetic:!0,runContext:{urlPattern:"^https://setapp\\.com/"},prehideSelectors:[],detectCmp:[{exists:".cookie-banner.js-cookie-banner"}],detectPopup:[{visible:".cookie-banner.js-cookie-banner"}],optIn:[{waitForThenClick:".cookie-banner.js-cookie-banner button"}],optOut:[{hide:".cookie-banner.js-cookie-banner"}]},{name:"sibbo",prehideSelectors:["sibbo-cmp-layout"],detectCmp:[{exists:"sibbo-cmp-layout"}],detectPopup:[{visible:"#rejectAllMain"}],optIn:[{click:"#acceptAllMain"}],optOut:[{click:"#rejectAllMain"}]},{name:"similarweb.com",cosmetic:!0,prehideSelectors:[".app-cookies-notification"],detectCmp:[{exists:".app-cookies-notification"}],detectPopup:[{exists:".app-layout .app-cookies-notification"}],optIn:[{click:"button.app-cookies-notification__dismiss"}],optOut:[{hide:".app-layout .app-cookies-notification"}]},{name:"Sirdata",cosmetic:!1,prehideSelectors:["#sd-cmp"],detectCmp:[{exists:"#sd-cmp"}],detectPopup:[{visible:"#sd-cmp"}],optIn:[{waitForThenClick:"#sd-cmp .sd-cmp-3cRQ2"}],optOut:[{waitForThenClick:["#sd-cmp","xpath///span[contains(., 'Do not accept') or contains(., 'Acceptera inte') or contains(., 'No aceptar') or contains(., 'Ikke acceptere') or contains(., 'Nicht akzeptieren') or contains(., 'Не приемам') or contains(., 'Να μην γίνει αποδοχή') or contains(., 'Niet accepteren') or contains(., 'Nepřijímat') or contains(., 'Nie akceptuj') or contains(., 'Nu acceptați') or contains(., 'Não aceitar') or contains(., 'Continuer sans accepter') or contains(., 'Non accettare') or contains(., 'Nem fogad el')]"]}]},{name:"snigel",detectCmp:[{exists:".snigel-cmp-framework"}],detectPopup:[{visible:".snigel-cmp-framework"}],optOut:[{click:"#sn-b-custom"},{click:"#sn-b-save"}],test:[{eval:"EVAL_SNIGEL_0"}],optIn:[{click:".snigel-cmp-framework #accept-choices"}]},{name:"steampowered.com",detectCmp:[{exists:".cookiepreferences_popup"},{visible:".cookiepreferences_popup"}],detectPopup:[{visible:".cookiepreferences_popup"}],optOut:[{click:"#rejectAllButton"}],optIn:[{click:"#acceptAllButton"}],test:[{wait:1e3},{eval:"EVAL_STEAMPOWERED_0"}]},{name:"strato.de",prehideSelectors:[".consent__wrapper"],runContext:{urlPattern:"^https://www\\.strato\\.de/"},detectCmp:[{exists:".consent"}],detectPopup:[{visible:".consent"}],optIn:[{click:"button.consentAgree"}],optOut:[{click:"button.consentSettings"},{waitForThenClick:"button#consentSubmit"}]},{name:"svt.se",vendorUrl:"https://www.svt.se/",runContext:{urlPattern:"^https://www\\.svt\\.se/"},prehideSelectors:["[class*=CookieConsent__root___]"],detectCmp:[{exists:"[class*=CookieConsent__root___]"}],detectPopup:[{visible:"[class*=CookieConsent__modal___]"}],optIn:[{waitForThenClick:"[class*=CookieConsent__modal___] > div > button[class*=primary]"}],optOut:[{waitForThenClick:"[class*=CookieConsent__modal___] > div > button[class*=secondary]:nth-child(2)"}],test:[{eval:"EVAL_SVT_TEST"}]},{name:"takealot.com",cosmetic:!0,prehideSelectors:['div[class^="cookies-banner-module_"]'],detectCmp:[{exists:'div[class^="cookies-banner-module_cookie-banner_"]'}],detectPopup:[{exists:'div[class^="cookies-banner-module_cookie-banner_"]'}],optIn:[{click:'button[class*="cookies-banner-module_dismiss-button_"]'}],optOut:[{hide:'div[class^="cookies-banner-module_"]'},{if:{exists:'div[class^="cookies-banner-module_small-cookie-banner_"]'},then:[{eval:"EVAL_TAKEALOT_0"}],else:[]}]},{name:"tarteaucitron.js",prehideSelectors:["#tarteaucitronRoot"],detectCmp:[{exists:"#tarteaucitronRoot"}],detectPopup:[{visible:"#tarteaucitronRoot #tarteaucitronAlertBig",check:"any"}],optIn:[{eval:"EVAL_TARTEAUCITRON_1"}],optOut:[{eval:"EVAL_TARTEAUCITRON_0"}],test:[{eval:"EVAL_TARTEAUCITRON_2",comment:"sometimes there are required categories, so we check that at least something is false"}]},{name:"taunton",vendorUrl:"https://www.taunton.com/",prehideSelectors:["#taunton-user-consent__overlay"],detectCmp:[{exists:"#taunton-user-consent__overlay"}],detectPopup:[{exists:"#taunton-user-consent__overlay:not([aria-hidden=true])"}],optIn:[{click:"#taunton-user-consent__toolbar input[type=checkbox]:not(:checked)"},{click:"#taunton-user-consent__toolbar button[type=submit]"}],optOut:[{click:"#taunton-user-consent__toolbar input[type=checkbox]:checked",optional:!0,all:!0},{click:"#taunton-user-consent__toolbar button[type=submit]"}],test:[{eval:"EVAL_TAUNTON_TEST"}]},{name:"Tealium",prehideSelectors:["#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs,#__tealiumImplicitmodal,#consent-layer"],detectCmp:[{exists:"#__tealiumGDPRecModal *,#__tealiumGDPRcpPrefs *,#__tealiumImplicitmodal *"},{eval:"EVAL_TEALIUM_0"}],detectPopup:[{visible:"#__tealiumGDPRecModal *,#__tealiumGDPRcpPrefs *,#__tealiumImplicitmodal *",check:"any"}],optOut:[{eval:"EVAL_TEALIUM_1"},{eval:"EVAL_TEALIUM_DONOTSELL"},{hide:"#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs,#__tealiumImplicitmodal"},{waitForThenClick:"#cm-acceptNone,.js-accept-essential-cookies",timeout:1e3,optional:!0}],optIn:[{hide:"#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs"},{eval:"EVAL_TEALIUM_2"}],test:[{eval:"EVAL_TEALIUM_3"},{eval:"EVAL_TEALIUM_DONOTSELL_CHECK"},{visible:"#__tealiumGDPRecModal,#__tealiumGDPRcpPrefs",check:"none"}]},{name:"temu",vendorUrl:"https://temu.com",runContext:{urlPattern:"^https://[^/]*temu\\.com/"},prehideSelectors:["._2d-8vq-W,._1UdBUwni"],detectCmp:[{exists:"._3YCsmIaS"}],detectPopup:[{visible:"._3YCsmIaS"}],optIn:[{waitForThenClick:"._3fKiu5wx._3zN5SumS._3tAK973O.IYOfhWEs.VGNGF1pA"}],optOut:[{waitForThenClick:"._3fKiu5wx._1_XToJBF._3tAK973O.IYOfhWEs.VGNGF1pA"}]},{name:"Termly",prehideSelectors:["#termly-code-snippet-support"],detectCmp:[{exists:"#termly-code-snippet-support"}],detectPopup:[{visible:"#termly-code-snippet-support div"}],optIn:[{waitForThenClick:'[data-tid="banner-accept"]'}],optOut:[{if:{exists:'[data-tid="banner-decline"]'},then:[{click:'[data-tid="banner-decline"]'}],else:[{click:".t-preference-button"},{wait:500},{if:{exists:".t-declineAllButton"},then:[{click:".t-declineAllButton"}],else:[{waitForThenClick:".t-preference-modal input[type=checkbox][checked]:not([disabled])",all:!0},{waitForThenClick:".t-saveButton"}]}]}]},{name:"termsfeed",vendorUrl:"https://termsfeed.com",comment:"v4.x.x",prehideSelectors:[".termsfeed-com---nb"],detectCmp:[{exists:".termsfeed-com---nb"}],detectPopup:[{visible:".termsfeed-com---nb"}],optIn:[{waitForThenClick:".cc-nb-okagree"}],optOut:[{waitForThenClick:".cc-nb-reject"}]},{name:"termsfeed3",vendorUrl:"https://termsfeed.com",comment:"v3.x.x",prehideSelectors:[".cc_dialog.cc_css_reboot,.cc_overlay_lock"],detectCmp:[{exists:".cc_dialog.cc_css_reboot"}],detectPopup:[{visible:".cc_dialog.cc_css_reboot"}],optIn:[{waitForThenClick:".cc_dialog.cc_css_reboot .cc_b_ok"}],optOut:[{if:{exists:".cc_dialog.cc_css_reboot .cc_b_cp"},then:[{click:".cc_dialog.cc_css_reboot .cc_b_cp"},{waitForVisible:".cookie-consent-preferences-dialog .cc_cp_f_save button"},{waitForThenClick:".cookie-consent-preferences-dialog .cc_cp_f_save button"}],else:[{hide:".cc_dialog.cc_css_reboot,.cc_overlay_lock"}]}]},{name:"Test page cosmetic CMP",cosmetic:!0,prehideSelectors:["#privacy-test-page-cmp-test-prehide"],detectCmp:[{exists:"#privacy-test-page-cmp-test-banner"}],detectPopup:[{visible:"#privacy-test-page-cmp-test-banner"}],optIn:[{waitFor:"#accept-all"},{click:"#accept-all"}],optOut:[{hide:"#privacy-test-page-cmp-test-banner"}],test:[{wait:500},{eval:"EVAL_TESTCMP_COSMETIC_0"}]},{name:"Test page CMP",prehideSelectors:["#reject-all"],detectCmp:[{exists:"#privacy-test-page-cmp-test"}],detectPopup:[{visible:"#privacy-test-page-cmp-test"}],optIn:[{waitFor:"#accept-all"},{click:"#accept-all"}],optOut:[{waitFor:"#reject-all"},{click:"#reject-all"}],test:[{eval:"EVAL_TESTCMP_0"}]},{name:"thalia.de",prehideSelectors:[".consent-banner-box"],detectCmp:[{exists:"consent-banner[component=consent-banner]"}],detectPopup:[{visible:".consent-banner-box"}],optIn:[{click:".button-zustimmen"}],optOut:[{click:"button[data-consent=disagree]"}]},{name:"thefreedictionary.com",prehideSelectors:["#cmpBanner"],detectCmp:[{exists:"#cmpBanner"}],detectPopup:[{visible:"#cmpBanner"}],optIn:[{eval:"EVAL_THEFREEDICTIONARY_1"}],optOut:[{eval:"EVAL_THEFREEDICTIONARY_0"}]},{name:"theverge",runContext:{frame:!1,main:!0,urlPattern:"^https://(www)?\\.theverge\\.com"},intermediate:!1,prehideSelectors:[".duet--cta--cookie-banner"],detectCmp:[{exists:".duet--cta--cookie-banner"}],detectPopup:[{visible:".duet--cta--cookie-banner"}],optIn:[{click:".duet--cta--cookie-banner button.tracking-12",all:!1}],optOut:[{click:".duet--cta--cookie-banner button.tracking-12 > span"}],test:[{eval:"EVAL_THEVERGE_0"}]},{name:"tidbits-com",cosmetic:!0,prehideSelectors:["#eu_cookie_law_widget-2"],detectCmp:[{exists:"#eu_cookie_law_widget-2"}],detectPopup:[{visible:"#eu_cookie_law_widget-2"}],optIn:[{click:"#eu-cookie-law form > input.accept"}],optOut:[{hide:"#eu_cookie_law_widget-2"}]},{name:"tractor-supply",runContext:{urlPattern:"^https://www\\.tractorsupply\\.com/"},cosmetic:!0,prehideSelectors:[".tsc-cookie-banner"],detectCmp:[{exists:".tsc-cookie-banner"}],detectPopup:[{visible:".tsc-cookie-banner"}],optIn:[{click:"#cookie-banner-cancel"}],optOut:[{hide:".tsc-cookie-banner"}]},{name:"trader-joes-com",cosmetic:!0,prehideSelectors:['div.aem-page > div[class^="CookiesAlert_cookiesAlert__"]'],detectCmp:[{exists:'div.aem-page > div[class^="CookiesAlert_cookiesAlert__"]'}],detectPopup:[{visible:'div.aem-page > div[class^="CookiesAlert_cookiesAlert__"]'}],optIn:[{click:'div[class^="CookiesAlert_cookiesAlert__container__"] button'}],optOut:[{hide:'div.aem-page > div[class^="CookiesAlert_cookiesAlert__"]'}]},{name:"transcend",vendorUrl:"https://unknown",cosmetic:!0,prehideSelectors:["#transcend-consent-manager"],detectCmp:[{exists:"#transcend-consent-manager"}],detectPopup:[{visible:"#transcend-consent-manager"}],optIn:[{waitForThenClick:["#transcend-consent-manager","#consentManagerMainDialog .inner-container button"]}],optOut:[{hide:"#transcend-consent-manager"}]},{name:"transip-nl",runContext:{urlPattern:"^https://www\\.transip\\.nl/"},prehideSelectors:["#consent-modal"],detectCmp:[{any:[{exists:"#consent-modal"},{exists:"#privacy-settings-content"}]}],detectPopup:[{any:[{visible:"#consent-modal"},{visible:"#privacy-settings-content"}]}],optIn:[{click:'button[type="submit"]'}],optOut:[{if:{exists:"#privacy-settings-content"},then:[{click:'button[type="submit"]'}],else:[{click:"div.one-modal__action-footer-column--secondary > a"}]}]},{name:"tropicfeel-com",prehideSelectors:["#shopify-section-cookies-controller"],detectCmp:[{exists:"#shopify-section-cookies-controller"}],detectPopup:[{visible:"#shopify-section-cookies-controller #cookies-controller-main-pane",check:"any"}],optIn:[{waitForThenClick:"#cookies-controller-main-pane form[data-form-allow-all] button"}],optOut:[{click:"#cookies-controller-main-pane a[data-tab-target=manage-cookies]"},{waitFor:"#manage-cookies-pane.active"},{click:"#manage-cookies-pane.active input[type=checkbox][checked]:not([disabled])",all:!0},{click:"#manage-cookies-pane.active button[type=submit]"}],test:[]},{name:"true-car",runContext:{urlPattern:"^https://www\\.truecar\\.com/"},cosmetic:!0,prehideSelectors:[['div[aria-labelledby="cookie-banner-heading"]']],detectCmp:[{exists:'div[aria-labelledby="cookie-banner-heading"]'}],detectPopup:[{visible:'div[aria-labelledby="cookie-banner-heading"]'}],optIn:[{click:'div[aria-labelledby="cookie-banner-heading"] > button[aria-label="Close"]'}],optOut:[{hide:'div[aria-labelledby="cookie-banner-heading"]'}]},{name:"truyo",prehideSelectors:["#truyo-consent-module"],detectCmp:[{exists:"#truyo-cookieBarContent"}],detectPopup:[{visible:"#truyo-consent-module"}],optIn:[{click:"button#acceptAllCookieButton"}],optOut:[{click:"button#declineAllCookieButton"}]},{name:"twitch-mobile",vendorUrl:"https://m.twitch.tv/",cosmetic:!0,runContext:{urlPattern:"^https?://m\\.twitch\\.tv"},prehideSelectors:[],detectCmp:[{exists:'.ReactModal__Overlay [href="https://www.twitch.tv/p/cookie-policy"]'}],detectPopup:[{visible:'.ReactModal__Overlay [href="https://www.twitch.tv/p/cookie-policy"]'}],optIn:[{waitForThenClick:'.ReactModal__Overlay:has([href="https://www.twitch.tv/p/cookie-policy"]) button'}],optOut:[{hide:'.ReactModal__Overlay:has([href="https://www.twitch.tv/p/cookie-policy"])'}]},{name:"twitch.tv",runContext:{urlPattern:"^https?://(www\\.)?twitch\\.tv"},prehideSelectors:["div:has(> .consent-banner .consent-banner__content--gdpr-v2),.ReactModalPortal:has([data-a-target=consent-modal-save])"],detectCmp:[{exists:".consent-banner .consent-banner__content--gdpr-v2"}],detectPopup:[{visible:".consent-banner .consent-banner__content--gdpr-v2"}],optIn:[{click:'button[data-a-target="consent-banner-accept"]'}],optOut:[{hide:"div:has(> .consent-banner .consent-banner__content--gdpr-v2)"},{click:'button[data-a-target="consent-banner-manage-preferences"]'},{waitFor:"input[type=checkbox][data-a-target=tw-checkbox]"},{click:"input[type=checkbox][data-a-target=tw-checkbox][checked]:not([disabled])",all:!0,optional:!0},{waitForThenClick:"[data-a-target=consent-modal-save]"},{waitForVisible:".ReactModalPortal:has([data-a-target=consent-modal-save])",check:"none"}]},{name:"twitter",runContext:{urlPattern:"^https://([a-z0-9-]+\\.)?twitter\\.com/"},prehideSelectors:['[data-testid="BottomBar"]'],detectCmp:[{exists:'[data-testid="BottomBar"] div'}],detectPopup:[{visible:'[data-testid="BottomBar"] div'}],optIn:[{waitForThenClick:'[data-testid="BottomBar"] > div:has(>div:first-child>div:last-child>span[role=button]) > div:last-child > div[role=button]:first-child'}],optOut:[{waitForThenClick:'[data-testid="BottomBar"] > div:has(>div:first-child>div:last-child>span[role=button]) > div:last-child > div[role=button]:last-child'}],TODOtest:[{eval:"EVAL_document.cookie.includes('d_prefs=MjoxLGNvbnNlbnRfdmVyc2lvbjoy')"}]},{name:"ubuntu.com",prehideSelectors:["dialog.cookie-policy"],detectCmp:[{any:[{exists:"dialog.cookie-policy header"},{exists:'xpath///*[@id="modal"]/div/header'}]}],detectPopup:[{any:[{visible:"dialog header"},{visible:'xpath///*[@id="modal"]/div/header'}]}],optIn:[{any:[{waitForThenClick:"#cookie-policy-button-accept"},{waitForThenClick:'xpath///*[@id="cookie-policy-button-accept"]'}]}],optOut:[{any:[{waitForThenClick:"button.js-manage"},{waitForThenClick:'xpath///*[@id="cookie-policy-content"]/p[4]/button[2]'}]},{waitForThenClick:"dialog.cookie-policy .p-switch__input:checked",optional:!0,all:!0,timeout:500},{any:[{waitForThenClick:"dialog.cookie-policy .js-save-preferences"},{waitForThenClick:'xpath///*[@id="modal"]/div/button'}]}],test:[{eval:"EVAL_UBUNTU_COM_0"}]},{name:"UK Cookie Consent",prehideSelectors:["#catapult-cookie-bar"],cosmetic:!0,detectCmp:[{exists:"#catapult-cookie-bar"}],detectPopup:[{exists:".has-cookie-bar #catapult-cookie-bar"}],optIn:[{click:"#catapultCookie"}],optOut:[{hide:"#catapult-cookie-bar"}],test:[{eval:"EVAL_UK_COOKIE_CONSENT_0"}]},{name:"urbanarmorgear-com",cosmetic:!0,prehideSelectors:['div[class^="Layout__CookieBannerContainer-"]'],detectCmp:[{exists:'div[class^="Layout__CookieBannerContainer-"]'}],detectPopup:[{visible:'div[class^="Layout__CookieBannerContainer-"]'}],optIn:[{click:'button[class^="CookieBanner__AcceptButton"]'}],optOut:[{hide:'div[class^="Layout__CookieBannerContainer-"]'}]},{name:"usercentrics-api",detectCmp:[{exists:"#usercentrics-root,#usercentrics-cmp-ui"}],detectPopup:[{eval:"EVAL_USERCENTRICS_API_0"},{if:{exists:"#usercentrics-cmp-ui"},then:[{waitForVisible:"#usercentrics-cmp-ui",timeout:2e3}],else:[{exists:["#usercentrics-root","[data-testid=uc-container]"]},{waitForVisible:"#usercentrics-root",timeout:2e3}]}],optIn:[{eval:"EVAL_USERCENTRICS_API_3"},{eval:"EVAL_USERCENTRICS_API_1"},{eval:"EVAL_USERCENTRICS_API_5"}],optOut:[{eval:"EVAL_USERCENTRICS_API_1"},{eval:"EVAL_USERCENTRICS_API_2"}],test:[{eval:"EVAL_USERCENTRICS_API_6"}]},{name:"usercentrics-button",detectCmp:[{exists:"#usercentrics-button"}],detectPopup:[{visible:"#usercentrics-button #uc-btn-accept-banner"}],optIn:[{click:"#usercentrics-button #uc-btn-accept-banner"}],optOut:[{click:"#usercentrics-button #uc-btn-deny-banner"}],test:[{eval:"EVAL_USERCENTRICS_BUTTON_0"}]},{name:"uswitch.com",runContext:{main:!0,frame:!1,urlPattern:"^https://(www\\.)?uswitch\\.com/"},prehideSelectors:[".ucb"],detectCmp:[{exists:".ucb-banner"}],detectPopup:[{visible:".ucb-banner"}],optIn:[{waitForThenClick:".ucb-banner .ucb-btn-accept"}],optOut:[{waitForThenClick:".ucb-banner .ucb-btn-save"}]},{name:"vodafone.de",runContext:{urlPattern:"^https://www\\.vodafone\\.de/"},prehideSelectors:[".dip-consent,.dip-consent-container"],detectCmp:[{exists:".dip-consent-container"}],detectPopup:[{visible:".dip-consent-content"}],optOut:[{click:'.dip-consent-btn[tabindex="2"]'}],optIn:[{click:'.dip-consent-btn[tabindex="1"]'}]},{name:"waitrose.com",prehideSelectors:["div[aria-labelledby=CookieAlertModalHeading]","section[data-test=initial-waitrose-cookie-consent-banner]","section[data-test=cookie-consent-modal]"],detectCmp:[{exists:"section[data-test=initial-waitrose-cookie-consent-banner]"}],detectPopup:[{visible:"section[data-test=initial-waitrose-cookie-consent-banner]"}],optIn:[{click:"button[data-test=accept-all]"}],optOut:[{click:"button[data-test=manage-cookies]"},{wait:200},{eval:"EVAL_WAITROSE_0"},{click:"button[data-test=submit]"}],test:[{eval:"EVAL_WAITROSE_1"}]},{name:"webflow",vendorUrl:"https://webflow.com/",prehideSelectors:[".fs-cc-components"],detectCmp:[{exists:".fs-cc-components"}],detectPopup:[{visible:".fs-cc-components"},{visible:"[fs-cc=banner]"}],optIn:[{wait:500},{waitForThenClick:"[fs-cc=banner] [fs-cc=allow]"}],optOut:[{wait:500},{waitForThenClick:"[fs-cc=banner] [fs-cc=deny]"}]},{name:"wetransfer.com",detectCmp:[{exists:".welcome__cookie-notice"}],detectPopup:[{visible:".welcome__cookie-notice"}],optIn:[{click:".welcome__button--accept"}],optOut:[{click:".welcome__button--decline"}]},{name:"whitepages.com",runContext:{urlPattern:"^https://www\\.whitepages\\.com/"},cosmetic:!0,prehideSelectors:[".cookie-wrapper, .cookie-overlay"],detectCmp:[{exists:".cookie-wrapper"}],detectPopup:[{visible:".cookie-overlay"}],optIn:[{click:'button[aria-label="Got it"]'}],optOut:[{hide:".cookie-wrapper"}]},{name:"wolframalpha",vendorUrl:"https://www.wolframalpha.com",prehideSelectors:[],cosmetic:!0,runContext:{urlPattern:"^https://www\\.wolframalpha\\.com/"},detectCmp:[{exists:"section._a_yb"}],detectPopup:[{visible:"section._a_yb"}],optIn:[{waitForThenClick:"section._a_yb button"}],optOut:[{hide:"section._a_yb"}]},{name:"woo-commerce-com",prehideSelectors:[".wccom-comp-privacy-banner .wccom-privacy-banner"],detectCmp:[{exists:".wccom-comp-privacy-banner .wccom-privacy-banner"}],detectPopup:[{exists:".wccom-comp-privacy-banner .wccom-privacy-banner"}],optIn:[{click:".wccom-privacy-banner__content-buttons button.is-primary"}],optOut:[{click:".wccom-privacy-banner__content-buttons button.is-secondary"},{waitForThenClick:"input[type=checkbox][checked]:not([disabled])",all:!0},{click:"div.wccom-modal__footer > button"}]},{name:"WP Cookie Notice for GDPR",vendorUrl:"https://wordpress.org/plugins/gdpr-cookie-consent/",prehideSelectors:["#gdpr-cookie-consent-bar"],detectCmp:[{exists:"#gdpr-cookie-consent-bar"}],detectPopup:[{visible:"#gdpr-cookie-consent-bar"}],optIn:[{waitForThenClick:"#gdpr-cookie-consent-bar #cookie_action_accept"}],optOut:[{waitForThenClick:"#gdpr-cookie-consent-bar #cookie_action_reject"}],test:[{eval:"EVAL_WP_COOKIE_NOTICE_0"}]},{name:"wpcc",cosmetic:!0,prehideSelectors:[".wpcc-container"],detectCmp:[{exists:".wpcc-container"}],detectPopup:[{exists:".wpcc-container .wpcc-message"}],optIn:[{click:".wpcc-compliance .wpcc-btn"}],optOut:[{hide:".wpcc-container"}]},{name:"xe.com",vendorUrl:"https://www.xe.com/",runContext:{urlPattern:"^https://www\\.xe\\.com/"},prehideSelectors:["[class*=ConsentBanner]"],detectCmp:[{exists:"[class*=ConsentBanner]"}],detectPopup:[{visible:"[class*=ConsentBanner]"}],optIn:[{waitForThenClick:"[class*=ConsentBanner] .egnScw"}],optOut:[{wait:1e3},{waitForThenClick:"[class*=ConsentBanner] .frDWEu"},{waitForThenClick:"[class*=ConsentBanner] .hXIpFU"}],test:[{eval:"EVAL_XE_TEST"}]},{name:"xhamster-eu",prehideSelectors:[".cookies-modal"],detectCmp:[{exists:".cookies-modal"}],detectPopup:[{exists:".cookies-modal"}],optIn:[{click:"button.cmd-button-accept-all"}],optOut:[{click:"button.cmd-button-reject-all"}]},{name:"xhamster-us",runContext:{urlPattern:"^https://(www\\.)?xhamster\\d?\\.com"},cosmetic:!0,prehideSelectors:[".cookie-announce"],detectCmp:[{exists:".cookie-announce"}],detectPopup:[{visible:".cookie-announce .announce-text"}],optIn:[{click:".cookie-announce button.xh-button"}],optOut:[{hide:".cookie-announce"}]},{name:"xing.com",detectCmp:[{exists:"div[class^=cookie-consent-CookieConsent]"}],detectPopup:[{exists:"div[class^=cookie-consent-CookieConsent]"}],optIn:[{click:"#consent-accept-button"}],optOut:[{click:"#consent-settings-button"},{click:".consent-banner-button-accept-overlay"}],test:[{eval:"EVAL_XING_0"}]},{name:"xnxx-com",cosmetic:!0,prehideSelectors:["#cookies-use-alert"],detectCmp:[{exists:"#cookies-use-alert"}],detectPopup:[{visible:"#cookies-use-alert"}],optIn:[{click:"#cookies-use-alert .close"}],optOut:[{hide:"#cookies-use-alert"}]},{name:"xvideos",vendorUrl:"https://xvideos.com",runContext:{urlPattern:"^https://[^/]*xvideos\\.com/"},prehideSelectors:[],detectCmp:[{exists:".disclaimer-opened #disclaimer-cookies"}],detectPopup:[{visible:".disclaimer-opened #disclaimer-cookies"}],optIn:[{waitForThenClick:"#disclaimer-accept_cookies"}],optOut:[{waitForThenClick:"#disclaimer-reject_cookies"}]},{name:"Yahoo",runContext:{urlPattern:"^https://consent\\.yahoo\\.com/v2/"},prehideSelectors:["#reject-all"],detectCmp:[{exists:"#consent-page"}],detectPopup:[{visible:"#consent-page"}],optIn:[{waitForThenClick:"#consent-page button[value=agree]"}],optOut:[{waitForThenClick:"#consent-page button[value=reject]"}]},{name:"youporn.com",cosmetic:!0,prehideSelectors:[".euCookieModal, #js_euCookieModal"],detectCmp:[{exists:".euCookieModal"}],detectPopup:[{exists:".euCookieModal, #js_euCookieModal"}],optIn:[{click:'button[name="user_acceptCookie"]'}],optOut:[{hide:".euCookieModal"}]},{name:"youtube-desktop",prehideSelectors:["tp-yt-iron-overlay-backdrop.opened","ytd-consent-bump-v2-lightbox"],detectCmp:[{exists:"ytd-consent-bump-v2-lightbox tp-yt-paper-dialog"},{exists:'ytd-consent-bump-v2-lightbox tp-yt-paper-dialog a[href^="https://consent.youtube.com/"]'}],detectPopup:[{visible:"ytd-consent-bump-v2-lightbox tp-yt-paper-dialog"}],optIn:[{waitForThenClick:"ytd-consent-bump-v2-lightbox .eom-buttons .eom-button-row:first-child ytd-button-renderer:last-child #button,ytd-consent-bump-v2-lightbox .eom-buttons .eom-button-row:first-child ytd-button-renderer:last-child button"},{wait:500}],optOut:[{waitForThenClick:"ytd-consent-bump-v2-lightbox .eom-buttons .eom-button-row:first-child ytd-button-renderer:first-child #button,ytd-consent-bump-v2-lightbox .eom-buttons .eom-button-row:first-child ytd-button-renderer:first-child button"},{wait:500}],test:[{wait:500},{eval:"EVAL_YOUTUBE_DESKTOP_0"}]},{name:"youtube-mobile",prehideSelectors:[".consent-bump-v2-lightbox"],detectCmp:[{exists:"ytm-consent-bump-v2-renderer"}],detectPopup:[{visible:"ytm-consent-bump-v2-renderer"}],optIn:[{waitForThenClick:"ytm-consent-bump-v2-renderer .privacy-terms + .one-col-dialog-buttons c3-material-button:first-child button, ytm-consent-bump-v2-renderer .privacy-terms + .one-col-dialog-buttons ytm-button-renderer:first-child button"},{wait:500}],optOut:[{waitForThenClick:"ytm-consent-bump-v2-renderer .privacy-terms + .one-col-dialog-buttons c3-material-button:nth-child(2) button, ytm-consent-bump-v2-renderer .privacy-terms + .one-col-dialog-buttons ytm-button-renderer:nth-child(2) button"},{wait:500}],test:[{wait:500},{eval:"EVAL_YOUTUBE_MOBILE_0"}]},{name:"zdf",prehideSelectors:["#zdf-cmp-banner-sdk"],detectCmp:[{exists:"#zdf-cmp-banner-sdk"}],detectPopup:[{visible:"#zdf-cmp-main.zdf-cmp-show"}],optIn:[{waitForThenClick:"#zdf-cmp-main #zdf-cmp-accept-btn"}],optOut:[{waitForThenClick:"#zdf-cmp-main #zdf-cmp-deny-btn"}],test:[]},{name:"zentralruf-de",runContext:{urlPattern:"^https://(www\\.)?zentralruf\\.de"},prehideSelectors:["#cookie_modal_wrapper"],detectCmp:[{exists:"#cookie_modal_wrapper"}],detectPopup:[{visible:"#cookie_modal_wrapper"}],optIn:[{waitForThenClick:"#cookie_modal_wrapper #cookie_modal_button_consent_all"}],optOut:[{waitForThenClick:"#cookie_modal_wrapper #cookie_modal_button_choose"}]}],C={"didomi.io":{detectors:[{presentMatcher:{target:{selector:"#didomi-host, #didomi-notice"},type:"css"},showingMatcher:{target:{selector:"body.didomi-popup-open, .didomi-notice-banner"},type:"css"}}],methods:[{action:{target:{selector:".didomi-popup-notice-buttons .didomi-button:not(.didomi-button-highlight), .didomi-notice-banner .didomi-learn-more-button"},type:"click"},name:"OPEN_OPTIONS"},{action:{actions:[{retries:50,target:{selector:"#didomi-purpose-cookies"},type:"waitcss",waitTime:50},{consents:[{description:"Share (everything) with others",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-share_whith_others]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-share_whith_others]:last-child"},type:"click"},type:"X"},{description:"Information storage and access",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-cookies]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-cookies]:last-child"},type:"click"},type:"D"},{description:"Content selection, offers and marketing",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-CL-T1Rgm7]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-CL-T1Rgm7]:last-child"},type:"click"},type:"E"},{description:"Analytics",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-analytics]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-analytics]:last-child"},type:"click"},type:"B"},{description:"Analytics",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-M9NRHJe3G]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-M9NRHJe3G]:last-child"},type:"click"},type:"B"},{description:"Ad and content selection",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-advertising_personalization]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-advertising_personalization]:last-child"},type:"click"},type:"F"},{description:"Ad and content selection",falseAction:{parent:{childFilter:{target:{selector:"#didomi-purpose-pub-ciblee"}},selector:".didomi-consent-popup-data-processing, .didomi-components-accordion-label-container"},target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-pub-ciblee]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-pub-ciblee]:last-child"},type:"click"},type:"F"},{description:"Ad and content selection - basics",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-q4zlJqdcD]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-q4zlJqdcD]:last-child"},type:"click"},type:"F"},{description:"Ad and content selection - partners and subsidiaries",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-partenaire-cAsDe8jC]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-partenaire-cAsDe8jC]:last-child"},type:"click"},type:"F"},{description:"Ad and content selection - social networks",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-p4em9a8m]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-p4em9a8m]:last-child"},type:"click"},type:"F"},{description:"Ad and content selection - others",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-autres-pub]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-autres-pub]:last-child"},type:"click"},type:"F"},{description:"Social networks",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-reseauxsociaux]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-reseauxsociaux]:last-child"},type:"click"},type:"A"},{description:"Social networks",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-social_media]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-social_media]:last-child"},type:"click"},type:"A"},{description:"Content selection",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-content_personalization]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-content_personalization]:last-child"},type:"click"},type:"E"},{description:"Ad delivery",falseAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-ad_delivery]:first-child"},type:"click"},trueAction:{target:{selector:".didomi-components-radio__option[aria-describedby=didomi-purpose-ad_delivery]:last-child"},type:"click"},type:"F"}],type:"consent"},{action:{consents:[{matcher:{childFilter:{target:{selector:":not(.didomi-components-radio__option--selected)"}},type:"css"},trueAction:{target:{selector:":nth-child(2)"},type:"click"},falseAction:{target:{selector:":first-child"},type:"click"},type:"X"}],type:"consent"},target:{selector:".didomi-components-radio"},type:"foreach"}],type:"list"},name:"DO_CONSENT"},{action:{parent:{selector:".didomi-consent-popup-footer .didomi-consent-popup-actions"},target:{selector:".didomi-components-button:first-child"},type:"click"},name:"SAVE_CONSENT"}]},oil:{detectors:[{presentMatcher:{target:{selector:".as-oil-content-overlay"},type:"css"},showingMatcher:{target:{selector:".as-oil-content-overlay"},type:"css"}}],methods:[{action:{actions:[{target:{selector:".as-js-advanced-settings"},type:"click"},{retries:"10",target:{selector:".as-oil-cpc__purpose-container"},type:"waitcss",waitTime:"250"}],type:"list"},name:"OPEN_OPTIONS"},{action:{actions:[{consents:[{matcher:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Information storage and access","Opbevaring af og adgang til oplysninger på din enhed"]},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Information storage and access","Opbevaring af og adgang til oplysninger på din enhed"]},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"D"},{matcher:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Personlige annoncer","Personalisation"]},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Personlige annoncer","Personalisation"]},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"E"},{matcher:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Annoncevalg, levering og rapportering","Ad selection, delivery, reporting"]},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Annoncevalg, levering og rapportering","Ad selection, delivery, reporting"]},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"F"},{matcher:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Personalisering af indhold","Content selection, delivery, reporting"]},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:["Personalisering af indhold","Content selection, delivery, reporting"]},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"E"},{matcher:{parent:{childFilter:{target:{selector:".as-oil-cpc__purpose-header",textFilter:["Måling","Measurement"]}},selector:".as-oil-cpc__purpose-container"},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{childFilter:{target:{selector:".as-oil-cpc__purpose-header",textFilter:["Måling","Measurement"]}},selector:".as-oil-cpc__purpose-container"},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"B"},{matcher:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:"Google"},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".as-oil-cpc__purpose-container",textFilter:"Google"},target:{selector:".as-oil-cpc__switch"},type:"click"},type:"F"}],type:"consent"}],type:"list"},name:"DO_CONSENT"},{action:{target:{selector:".as-oil__btn-optin"},type:"click"},name:"SAVE_CONSENT"},{action:{target:{selector:"div.as-oil"},type:"hide"},name:"HIDE_CMP"}]},optanon:{detectors:[{presentMatcher:{target:{selector:"#optanon-menu, .optanon-alert-box-wrapper"},type:"css"},showingMatcher:{target:{displayFilter:!0,selector:".optanon-alert-box-wrapper"},type:"css"}}],methods:[{action:{actions:[{target:{selector:".optanon-alert-box-wrapper .optanon-toggle-display, a[onclick*='OneTrust.ToggleInfoDisplay()'], a[onclick*='Optanon.ToggleInfoDisplay()']"},type:"click"}],type:"list"},name:"OPEN_OPTIONS"},{action:{actions:[{target:{selector:".preference-menu-item #Your-privacy"},type:"click"},{target:{selector:"#optanon-vendor-consent-text"},type:"click"},{action:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"X"}],type:"consent"},target:{selector:"#optanon-vendor-consent-list .vendor-item"},type:"foreach"},{target:{selector:".vendor-consent-back-link"},type:"click"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-performance"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-performance"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-functional"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-functional"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"E"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-advertising"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-advertising"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-social"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-social"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Social Media Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Social Media Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Personalisation"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Personalisation"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"E"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Site monitoring cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Site monitoring cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Third party privacy-enhanced content"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Third party privacy-enhanced content"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"X"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Performance & Advertising Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Performance & Advertising Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Information storage and access"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Information storage and access"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"D"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Ad selection, delivery, reporting"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Ad selection, delivery, reporting"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Content selection, delivery, reporting"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Content selection, delivery, reporting"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"E"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Measurement"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Measurement"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Recommended Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Recommended Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"X"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Unclassified Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Unclassified Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"X"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Analytical Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Analytical Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"B"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Marketing Cookies"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Marketing Cookies"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Personalization"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Personalization"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"E"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Ad Selection, Delivery & Reporting"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Ad Selection, Delivery & Reporting"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},type:"ifcss"},{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Content Selection, Delivery & Reporting"},trueAction:{actions:[{parent:{selector:"#optanon-menu, .optanon-menu"},target:{selector:".menu-item-necessary",textFilter:"Content Selection, Delivery & Reporting"},type:"click"},{consents:[{matcher:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status input"},type:"checkbox"},toggleAction:{parent:{selector:"#optanon-popup-body-right"},target:{selector:".optanon-status label"},type:"click"},type:"E"}],type:"consent"}],type:"list"},type:"ifcss"}],type:"list"},name:"DO_CONSENT"},{action:{parent:{selector:".optanon-save-settings-button"},target:{selector:".optanon-white-button-middle"},type:"click"},name:"SAVE_CONSENT"},{action:{actions:[{target:{selector:"#optanon-popup-wrapper"},type:"hide"},{target:{selector:"#optanon-popup-bg"},type:"hide"},{target:{selector:".optanon-alert-box-wrapper"},type:"hide"}],type:"list"},name:"HIDE_CMP"}]},quantcast2:{detectors:[{presentMatcher:{target:{selector:"[data-tracking-opt-in-overlay]"},type:"css"},showingMatcher:{target:{selector:"[data-tracking-opt-in-overlay] [data-tracking-opt-in-learn-more]"},type:"css"}}],methods:[{action:{target:{selector:"[data-tracking-opt-in-overlay] [data-tracking-opt-in-learn-more]"},type:"click"},name:"OPEN_OPTIONS"},{action:{actions:[{type:"wait",waitTime:500},{action:{actions:[{target:{selector:"div",textFilter:["Information storage and access"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"D"}],type:"consent"},type:"ifcss"},{target:{selector:"div",textFilter:["Personalization"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"F"}],type:"consent"},type:"ifcss"},{target:{selector:"div",textFilter:["Ad selection, delivery, reporting"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"F"}],type:"consent"},type:"ifcss"},{target:{selector:"div",textFilter:["Content selection, delivery, reporting"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"E"}],type:"consent"},type:"ifcss"},{target:{selector:"div",textFilter:["Measurement"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"B"}],type:"consent"},type:"ifcss"},{target:{selector:"div",textFilter:["Other Partners"]},trueAction:{consents:[{matcher:{target:{selector:"input"},type:"checkbox"},toggleAction:{target:{selector:"label"},type:"click"},type:"X"}],type:"consent"},type:"ifcss"}],type:"list"},parent:{childFilter:{target:{selector:"input"}},selector:"[data-tracking-opt-in-overlay] > div > div"},target:{childFilter:{target:{selector:"input"}},selector:":scope > div"},type:"foreach"}],type:"list"},name:"DO_CONSENT"},{action:{target:{selector:"[data-tracking-opt-in-overlay] [data-tracking-opt-in-save]"},type:"click"},name:"SAVE_CONSENT"}]},springer:{detectors:[{presentMatcher:{parent:null,target:{selector:".cmp-app_gdpr"},type:"css"},showingMatcher:{parent:null,target:{displayFilter:!0,selector:".cmp-popup_popup"},type:"css"}}],methods:[{action:{actions:[{target:{selector:".cmp-intro_rejectAll"},type:"click"},{type:"wait",waitTime:250},{target:{selector:".cmp-purposes_purposeItem:not(.cmp-purposes_selectedPurpose)"},type:"click"}],type:"list"},name:"OPEN_OPTIONS"},{action:{consents:[{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Przechowywanie informacji na urządzeniu lub dostęp do nich",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Przechowywanie informacji na urządzeniu lub dostęp do nich",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"D"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór podstawowych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór podstawowych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"F"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Tworzenie profilu spersonalizowanych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Tworzenie profilu spersonalizowanych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"F"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór spersonalizowanych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór spersonalizowanych reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"E"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Tworzenie profilu spersonalizowanych treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Tworzenie profilu spersonalizowanych treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"E"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór spersonalizowanych treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Wybór spersonalizowanych treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"B"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Pomiar wydajności reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Pomiar wydajności reklam",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"B"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Pomiar wydajności treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Pomiar wydajności treści",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"B"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Stosowanie badań rynkowych w celu generowania opinii odbiorców",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Stosowanie badań rynkowych w celu generowania opinii odbiorców",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"X"},{matcher:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Opracowywanie i ulepszanie produktów",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch .cmp-switch_isSelected"},type:"css"},toggleAction:{parent:{selector:".cmp-purposes_detailHeader",textFilter:"Opracowywanie i ulepszanie produktów",childFilter:{target:{selector:".cmp-switch_switch"}}},target:{selector:".cmp-switch_switch:not(.cmp-switch_isSelected)"},type:"click"},type:"X"}],type:"consent"},name:"DO_CONSENT"},{action:{target:{selector:".cmp-details_save"},type:"click"},name:"SAVE_CONSENT"}]},wordpressgdpr:{detectors:[{presentMatcher:{parent:null,target:{selector:".wpgdprc-consent-bar"},type:"css"},showingMatcher:{parent:null,target:{displayFilter:!0,selector:".wpgdprc-consent-bar"},type:"css"}}],methods:[{action:{parent:null,target:{selector:".wpgdprc-consent-bar .wpgdprc-consent-bar__settings",textFilter:null},type:"click"},name:"OPEN_OPTIONS"},{action:{actions:[{target:{selector:".wpgdprc-consent-modal .wpgdprc-button",textFilter:"Eyeota"},type:"click"},{consents:[{description:"Eyeota Cookies",matcher:{parent:{selector:".wpgdprc-consent-modal__description",textFilter:"Eyeota"},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".wpgdprc-consent-modal__description",textFilter:"Eyeota"},target:{selector:"label"},type:"click"},type:"X"}],type:"consent"},{target:{selector:".wpgdprc-consent-modal .wpgdprc-button",textFilter:"Advertising"},type:"click"},{consents:[{description:"Advertising Cookies",matcher:{parent:{selector:".wpgdprc-consent-modal__description",textFilter:"Advertising"},target:{selector:"input"},type:"checkbox"},toggleAction:{parent:{selector:".wpgdprc-consent-modal__description",textFilter:"Advertising"},target:{selector:"label"},type:"click"},type:"F"}],type:"consent"}],type:"list"},name:"DO_CONSENT"},{action:{parent:null,target:{selector:".wpgdprc-button",textFilter:"Save my settings"},type:"click"},name:"SAVE_CONSENT"}]}},v={autoconsent:w,consentomatic:C},f=Object.freeze({__proto__:null,autoconsent:w,consentomatic:C,default:v});const A=new class{constructor(e,t=null,o=null){if(this.id=n(),this.rules=[],this.foundCmp=null,this.state={lifecycle:"loading",prehideOn:!1,findCmpAttempts:0,detectedCmps:[],detectedPopups:[],selfTest:null},a.sendContentMessage=e,this.sendContentMessage=e,this.rules=[],this.updateState({lifecycle:"loading"}),this.addDynamicRules(),t)this.initialize(t,o);else{o&&this.parseDeclarativeRules(o);e({type:"init",url:window.location.href}),this.updateState({lifecycle:"waitingForInitResponse"})}this.domActions=new class{constructor(e){this.autoconsentInstance=e}click(e,t=!1){const o=this.elementSelector(e);return this.autoconsentInstance.config.logs.rulesteps&&console.log("[click]",e,t,o),o.length>0&&(t?o.forEach((e=>e.click())):o[0].click()),o.length>0}elementExists(e){return this.elementSelector(e).length>0}elementVisible(e,t){const o=this.elementSelector(e),c=new Array(o.length);return o.forEach(((e,t)=>{c[t]=k(e)})),"none"===t?c.every((e=>!e)):0!==c.length&&("any"===t?c.some((e=>e)):c.every((e=>e)))}waitForElement(e,t=1e4){const o=Math.ceil(t/200);return this.autoconsentInstance.config.logs.rulesteps&&console.log("[waitForElement]",e),h((()=>this.elementSelector(e).length>0),o,200)}waitForVisible(e,t=1e4,o="any"){return h((()=>this.elementVisible(e,o)),Math.ceil(t/200),200)}async waitForThenClick(e,t=1e4,o=!1){return await this.waitForElement(e,t),this.click(e,o)}wait(e){return new Promise((t=>{setTimeout((()=>{t(!0)}),e)}))}hide(e,t){return m(u(),e,t)}prehide(e){const t=u("autoconsent-prehide");return this.autoconsentInstance.config.logs.lifecycle&&console.log("[prehide]",t,location.href),m(t,e,"opacity")}undoPrehide(){const e=u("autoconsent-prehide");return this.autoconsentInstance.config.logs.lifecycle&&console.log("[undoprehide]",e,location.href),e&&e.remove(),!!e}querySingleReplySelector(e,t=document){if(e.startsWith("aria/"))return[];if(e.startsWith("xpath/")){const o=e.slice(6),c=document.evaluate(o,t,null,XPathResult.ANY_TYPE,null);let i=null;const n=[];for(;i=c.iterateNext();)n.push(i);return n}return e.startsWith("text/")||e.startsWith("pierce/")?[]:t.shadowRoot?Array.from(t.shadowRoot.querySelectorAll(e)):Array.from(t.querySelectorAll(e))}querySelectorChain(e){let t,o=document;for(const c of e){if(t=this.querySingleReplySelector(c,o),0===t.length)return[];o=t[0]}return t}elementSelector(e){return"string"==typeof e?this.querySingleReplySelector(e):this.querySelectorChain(e)}}(this)}initialize(e,t){const o=b(e);if(o.logs.lifecycle&&console.log("autoconsent init",window.location.href),this.config=o,o.enabled){if(t&&this.parseDeclarativeRules(t),this.rules=function(e,t){return e.filter((e=>(!t.disabledCmps||!t.disabledCmps.includes(e.name))&&(t.enableCosmeticRules||!e.isCosmetic)))}(this.rules,o),e.enablePrehide)if(document.documentElement)this.prehideElements();else{const e=()=>{window.removeEventListener("DOMContentLoaded",e),this.prehideElements()};window.addEventListener("DOMContentLoaded",e)}if("loading"===document.readyState){const e=()=>{window.removeEventListener("DOMContentLoaded",e),this.start()};window.addEventListener("DOMContentLoaded",e)}else this.start();this.updateState({lifecycle:"initialized"})}else o.logs.lifecycle&&console.log("autoconsent is disabled")}addDynamicRules(){y.forEach((e=>{this.rules.push(new e(this))}))}parseDeclarativeRules(e){Object.keys(e.consentomatic).forEach((t=>{this.addConsentomaticCMP(t,e.consentomatic[t])})),e.autoconsent.forEach((e=>{this.addDeclarativeCMP(e)}))}addDeclarativeCMP(e){this.rules.push(new d(e,this))}addConsentomaticCMP(e,t){this.rules.push(new class{constructor(e,t){this.name=e,this.config=t,this.methods=new Map,this.runContext=l,this.isCosmetic=!1,t.methods.forEach((e=>{e.action&&this.methods.set(e.name,e.action)})),this.hasSelfTest=!1}get isIntermediate(){return!1}checkRunContext(){return!0}async detectCmp(){return this.config.detectors.map((e=>o(e.presentMatcher))).some((e=>!!e))}async detectPopup(){return this.config.detectors.map((e=>o(e.showingMatcher))).some((e=>!!e))}async executeAction(e,t){return!this.methods.has(e)||c(this.methods.get(e),t)}async optOut(){return await this.executeAction("HIDE_CMP"),await this.executeAction("OPEN_OPTIONS"),await this.executeAction("HIDE_CMP"),await this.executeAction("DO_CONSENT",[]),await this.executeAction("SAVE_CONSENT"),!0}async optIn(){return await this.executeAction("HIDE_CMP"),await this.executeAction("OPEN_OPTIONS"),await this.executeAction("HIDE_CMP"),await this.executeAction("DO_CONSENT",["D","A","B","E","F","X"]),await this.executeAction("SAVE_CONSENT"),!0}async openCmp(){return await this.executeAction("HIDE_CMP"),await this.executeAction("OPEN_OPTIONS"),!0}async test(){return!0}}(`com_${e}`,t))}start(){window.requestIdleCallback?window.requestIdleCallback((()=>this._start()),{timeout:500}):this._start()}async _start(){const e=this.config.logs;e.lifecycle&&console.log(`Detecting CMPs on ${window.location.href}`),this.updateState({lifecycle:"started"});const t=await this.findCmp(this.config.detectRetries);if(this.updateState({detectedCmps:t.map((e=>e.name))}),0===t.length)return e.lifecycle&&console.log("no CMP found",location.href),this.config.enablePrehide&&this.undoPrehide(),this.updateState({lifecycle:"nothingDetected"}),!1;this.updateState({lifecycle:"cmpDetected"});const o=[],c=[];for(const e of t)e.isCosmetic?c.push(e):o.push(e);let i=!1,n=await this.detectPopups(o,(async e=>{i=await this.handlePopup(e)}));if(0===n.length&&(n=await this.detectPopups(c,(async e=>{i=await this.handlePopup(e)}))),0===n.length)return e.lifecycle&&console.log("no popup found"),this.config.enablePrehide&&this.undoPrehide(),!1;if(n.length>1){const t={msg:"Found multiple CMPs, check the detection rules.",cmps:n.map((e=>e.name))};e.errors&&console.warn(t.msg,t.cmps),this.sendContentMessage({type:"autoconsentError",details:t})}return i}async findCmp(e){const t=this.config.logs;this.updateState({findCmpAttempts:this.state.findCmpAttempts+1});const o=[];for(const e of this.rules)try{if(!e.checkRunContext())continue;await e.detectCmp()&&(t.lifecycle&&console.log(`Found CMP: ${e.name} ${window.location.href}`),this.sendContentMessage({type:"cmpDetected",url:location.href,cmp:e.name}),o.push(e))}catch(o){t.errors&&console.warn(`error detecting ${e.name}`,o)}return 0===o.length&&e>0?(await this.domActions.wait(500),this.findCmp(e-1)):o}async detectPopup(e){if(await this.waitForPopup(e).catch((t=>(this.config.logs.errors&&console.warn(`error waiting for a popup for ${e.name}`,t),!1))))return this.updateState({detectedPopups:this.state.detectedPopups.concat([e.name])}),this.sendContentMessage({type:"popupFound",cmp:e.name,url:location.href}),e;throw new Error("Popup is not shown")}async detectPopups(e,t){const o=e.map((e=>this.detectPopup(e)));await Promise.any(o).then((e=>{t(e)})).catch((()=>null));const c=await Promise.allSettled(o),i=[];for(const e of c)"fulfilled"===e.status&&i.push(e.value);return i}async handlePopup(e){return this.updateState({lifecycle:"openPopupDetected"}),this.config.enablePrehide&&!this.state.prehideOn&&this.prehideElements(),this.foundCmp=e,"optOut"===this.config.autoAction?await this.doOptOut():"optIn"===this.config.autoAction?await this.doOptIn():(this.config.logs.lifecycle&&console.log("waiting for opt-out signal...",location.href),!0)}async doOptOut(){const e=this.config.logs;let t;return this.updateState({lifecycle:"runningOptOut"}),this.foundCmp?(e.lifecycle&&console.log(`CMP ${this.foundCmp.name}: opt out on ${window.location.href}`),t=await this.foundCmp.optOut(),e.lifecycle&&console.log(`${this.foundCmp.name}: opt out result ${t}`)):(e.errors&&console.log("no CMP to opt out"),t=!1),this.config.enablePrehide&&this.undoPrehide(),this.sendContentMessage({type:"optOutResult",cmp:this.foundCmp?this.foundCmp.name:"none",result:t,scheduleSelfTest:this.foundCmp&&this.foundCmp.hasSelfTest,url:location.href}),t&&!this.foundCmp.isIntermediate?(this.sendContentMessage({type:"autoconsentDone",cmp:this.foundCmp.name,isCosmetic:this.foundCmp.isCosmetic,url:location.href}),this.updateState({lifecycle:"done"})):this.updateState({lifecycle:t?"optOutSucceeded":"optOutFailed"}),t}async doOptIn(){const e=this.config.logs;let t;return this.updateState({lifecycle:"runningOptIn"}),this.foundCmp?(e.lifecycle&&console.log(`CMP ${this.foundCmp.name}: opt in on ${window.location.href}`),t=await this.foundCmp.optIn(),e.lifecycle&&console.log(`${this.foundCmp.name}: opt in result ${t}`)):(e.errors&&console.log("no CMP to opt in"),t=!1),this.config.enablePrehide&&this.undoPrehide(),this.sendContentMessage({type:"optInResult",cmp:this.foundCmp?this.foundCmp.name:"none",result:t,scheduleSelfTest:!1,url:location.href}),t&&!this.foundCmp.isIntermediate?(this.sendContentMessage({type:"autoconsentDone",cmp:this.foundCmp.name,isCosmetic:this.foundCmp.isCosmetic,url:location.href}),this.updateState({lifecycle:"done"})):this.updateState({lifecycle:t?"optInSucceeded":"optInFailed"}),t}async doSelfTest(){const e=this.config.logs;let t;return this.foundCmp?(e.lifecycle&&console.log(`CMP ${this.foundCmp.name}: self-test on ${window.location.href}`),t=await this.foundCmp.test()):(e.errors&&console.log("no CMP to self test"),t=!1),this.sendContentMessage({type:"selfTestResult",cmp:this.foundCmp?this.foundCmp.name:"none",result:t,url:location.href}),this.updateState({selfTest:t}),t}async waitForPopup(e,t=5,o=500){const c=this.config.logs;c.lifecycle&&console.log("checking if popup is open...",e.name);const i=await e.detectPopup().catch((t=>(c.errors&&console.warn(`error detecting popup for ${e.name}`,t),!1)));return!i&&t>0?(await this.domActions.wait(o),this.waitForPopup(e,t-1,o)):(c.lifecycle&&console.log(e.name,"popup is "+(i?"open":"not open")),i)}prehideElements(){const e=this.config.logs,t=this.rules.filter((e=>e.prehideSelectors&&e.checkRunContext())).reduce(((e,t)=>[...e,...t.prehideSelectors]),["#didomi-popup,.didomi-popup-container,.didomi-popup-notice,.didomi-consent-popup-preferences,#didomi-notice,.didomi-popup-backdrop,.didomi-screen-medium"]);return this.updateState({prehideOn:!0}),setTimeout((()=>{this.config.enablePrehide&&this.state.prehideOn&&!["runningOptOut","runningOptIn"].includes(this.state.lifecycle)&&(e.lifecycle&&console.log("Process is taking too long, unhiding elements"),this.undoPrehide())}),this.config.prehideTimeout||2e3),this.domActions.prehide(t.join(","))}undoPrehide(){return this.updateState({prehideOn:!1}),this.domActions.undoPrehide()}updateState(e){Object.assign(this.state,e),this.sendContentMessage({type:"report",instanceId:this.id,url:window.location.href,mainFrame:window.top===window.self,state:this.state})}async receiveMessageCallback(e){const t=this.config?.logs;switch(t?.messages&&console.log("received from background",e,window.location.href),e.type){case"initResp":this.initialize(e.config,e.rules);break;case"optIn":await this.doOptIn();break;case"optOut":await this.doOptOut();break;case"selfTest":await this.doSelfTest();break;case"evalResp":!function(e,t){const o=a.pending.get(e);o?(a.pending.delete(e),o.timer&&window.clearTimeout(o.timer),o.resolve(t)):console.warn("no eval #",e)}(e.id,e.result)}}}((e=>{window.webkit.messageHandlers[e.type]&&window.webkit.messageHandlers[e.type].postMessage(e).then((e=>{A.receiveMessageCallback(e)}))}),null,f);window.autoconsentMessageCallback=e=>{A.receiveMessageCallback(e)}}(); diff --git a/package-lock.json b/package-lock.json index d6a96e48baf..cf3dbe14ae7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "macos-browser", "version": "1.0.0", "dependencies": { - "@duckduckgo/autoconsent": "^10.10.0" + "@duckduckgo/autoconsent": "^10.13.0" }, "devDependencies": { "@rollup/plugin-json": "^4.1.0", @@ -53,9 +53,13 @@ } }, "node_modules/@duckduckgo/autoconsent": { - "version": "10.10.0", - "resolved": "https://registry.npmjs.org/@duckduckgo/autoconsent/-/autoconsent-10.10.0.tgz", - "integrity": "sha512-ewY0Rrpp/FiFS8tf7qO4+iuAM5h/nSo8jdBQbpOQ1hI7aCP5pIdrZehJWIO7mkiNboVKAaP3p1WBhydIjfQDFA==" + "version": "10.13.0", + "resolved": "https://registry.npmjs.org/@duckduckgo/autoconsent/-/autoconsent-10.13.0.tgz", + "integrity": "sha512-tR2XpSjA0Y4IC+Ql0J1e9B29Bz3qMEQW/+6gxJ6DRmvu0D8MsKvw0pST2rD/Q3+Mp9rL/FCklB/2X73hLK17LA==", + "license": "MPL-2.0", + "dependencies": { + "tldts-experimental": "^6.1.37" + } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.2", @@ -571,6 +575,21 @@ "engines": { "node": ">=10" } + }, + "node_modules/tldts-core": { + "version": "6.1.37", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.37.tgz", + "integrity": "sha512-q6M/RBjZcUoF/KRhHFuGrcnaXLaXH8kHKH/e8XaAd9ULGYYhB32kr1ceIXR77a57OxRB/NR471BcYwU7jf4PAg==", + "license": "MIT" + }, + "node_modules/tldts-experimental": { + "version": "6.1.37", + "resolved": "https://registry.npmjs.org/tldts-experimental/-/tldts-experimental-6.1.37.tgz", + "integrity": "sha512-GnuPXda/PzXoPqq4KCiXsiYoKBXV/oonfEY97hwadYmHzK6wJxLF8FPeRDGQPHP5RkphfcDGnAIMZthvqYrfSA==", + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.37" + } } } } diff --git a/package.json b/package.json index 68333b551a5..5d09ba3e0ce 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,6 @@ "rollup-plugin-terser": "^7.0.2" }, "dependencies": { - "@duckduckgo/autoconsent": "^10.10.0" + "@duckduckgo/autoconsent": "^10.13.0" } } From 149b303f0c4be53f452a4f2ff662dd31c3c05adf Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Sun, 4 Aug 2024 13:00:23 -0700 Subject: [PATCH 06/32] Add RMF `messageShown` attribute (#3062) Task/Issue URL: https://app.asana.com/0/1199333091098016/1207959177057413/f Tech Design URL: CC: Description: This PR adds support for the RMF messageShown attribute. --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- .../RemoteMessagingConfigMatcherProvider.swift | 2 ++ LocalPackages/DataBrokerProtection/Package.swift | 2 +- LocalPackages/NetworkProtectionMac/Package.swift | 2 +- LocalPackages/SubscriptionUI/Package.swift | 2 +- UnitTests/RemoteMessaging/MockRemoteMessagingStore.swift | 6 ++++++ 7 files changed, 14 insertions(+), 6 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 58947dc20f3..388a3a24fac 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -13370,7 +13370,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 178.0.0; + version = 179.0.0; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 2fa187fb002..03c17237853 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "ebad3db46e09913ac4c0e0c62085dcb40a6d6253", - "version" : "178.0.0" + "revision" : "dfddead0e1e4735a021d3affb05b64fea561a807", + "version" : "179.0.0" } }, { diff --git a/DuckDuckGo/RemoteMessaging/RemoteMessagingConfigMatcherProvider.swift b/DuckDuckGo/RemoteMessaging/RemoteMessagingConfigMatcherProvider.swift index 5aac8a4f142..d6a11fdc058 100644 --- a/DuckDuckGo/RemoteMessaging/RemoteMessagingConfigMatcherProvider.swift +++ b/DuckDuckGo/RemoteMessaging/RemoteMessagingConfigMatcherProvider.swift @@ -124,6 +124,7 @@ final class RemoteMessagingConfigMatcherProvider: RemoteMessagingConfigMatcherPr } let dismissedMessageIds = store.fetchDismissedRemoteMessageIDs() + let shownMessageIds = store.fetchShownRemoteMessageIDs() #if APPSTORE let isInstalledMacAppStore = true @@ -155,6 +156,7 @@ final class RemoteMessagingConfigMatcherProvider: RemoteMessagingConfigMatcherPr isPrivacyProSubscriptionExpiring: isPrivacyProSubscriptionExpiring, isPrivacyProSubscriptionExpired: isPrivacyProSubscriptionExpired, dismissedMessageIds: dismissedMessageIds, + shownMessageIds: shownMessageIds, pinnedTabsCount: pinnedTabsManager.tabCollection.tabs.count, hasCustomHomePage: startupPreferencesPersistor().launchToCustomHomePage, isDuckPlayerOnboarded: duckPlayerPreferencesPersistor.youtubeOverlayAnyButtonPressed, diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index 6785bcd4980..541a8544e50 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "178.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "179.0.0"), .package(path: "../SwiftUIExtensions"), .package(path: "../XPCHelper"), ], diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index bb1cbb7e170..54476802517 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -32,7 +32,7 @@ let package = Package( .library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "178.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "179.0.0"), .package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"), .package(path: "../AppLauncher"), .package(path: "../UDSHelper"), diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index c87fc52740f..6f04c63220f 100644 --- a/LocalPackages/SubscriptionUI/Package.swift +++ b/LocalPackages/SubscriptionUI/Package.swift @@ -12,7 +12,7 @@ let package = Package( targets: ["SubscriptionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "178.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "179.0.0"), .package(path: "../SwiftUIExtensions") ], targets: [ diff --git a/UnitTests/RemoteMessaging/MockRemoteMessagingStore.swift b/UnitTests/RemoteMessaging/MockRemoteMessagingStore.swift index e1d9fd397ff..46c967eeab3 100644 --- a/UnitTests/RemoteMessaging/MockRemoteMessagingStore.swift +++ b/UnitTests/RemoteMessaging/MockRemoteMessagingStore.swift @@ -25,6 +25,7 @@ class MockRemoteMessagingStore: RemoteMessagingStoring { var fetchScheduledRemoteMessageCalls = 0 var fetchRemoteMessageCalls = 0 var hasShownRemoteMessageCalls = 0 + var fetchShownRemoteMessageIdsCalls = 0 var hasDismissedRemoteMessageCalls = 0 var dismissRemoteMessageCalls = 0 var fetchDismissedRemoteMessageIdsCalls = 0 @@ -74,6 +75,11 @@ class MockRemoteMessagingStore: RemoteMessagingStoring { return shownRemoteMessagesIDs.contains(id) } + func fetchShownRemoteMessageIDs() -> [String] { + fetchShownRemoteMessageIdsCalls += 1 + return shownRemoteMessagesIDs + } + func hasDismissedRemoteMessage(withID id: String) -> Bool { hasDismissedRemoteMessageCalls += 1 return dismissedRemoteMessagesIDs.contains(id) From d55ef6be9bdd54df0927538ff39e67d8f4f0fbce Mon Sep 17 00:00:00 2001 From: bwaresiak Date: Mon, 5 Aug 2024 02:22:37 +0200 Subject: [PATCH 07/32] Update BSK usage after recent tweaks to DB API (#3033) Task/Issue URL: https://app.asana.com/0/856498667320406/1207875839908777/f Description: Update BSK to latest version. --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- .../xcschemes/sandbox-test-tool.xcscheme | 2 +- DuckDuckGo/Application/AppDelegate.swift | 16 +++++++--------- .../Legacy/LegacyBookmarksStoreMigration.swift | 4 ++-- LocalPackages/DataBrokerProtection/Package.swift | 2 +- LocalPackages/NetworkProtectionMac/Package.swift | 2 +- LocalPackages/SubscriptionUI/Package.swift | 2 +- 8 files changed, 16 insertions(+), 18 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 388a3a24fac..4efd45bc80e 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -13370,7 +13370,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 179.0.0; + version = 180.0.0; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 03c17237853..d08cec1c367 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "dfddead0e1e4735a021d3affb05b64fea561a807", - "version" : "179.0.0" + "revision" : "92ecebfb4172ab9561959a07d7ef7037aea8c6e1", + "version" : "180.0.0" } }, { diff --git a/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/sandbox-test-tool.xcscheme b/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/sandbox-test-tool.xcscheme index 41730d70695..eb7e5e26bb6 100644 --- a/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/sandbox-test-tool.xcscheme +++ b/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/sandbox-test-tool.xcscheme @@ -1,7 +1,7 @@ + version = "1.8"> { _, error, _, _ in + do { + let formFactorFavMigration = BookmarkFormFactorFavoritesMigration() + let favoritesOrder = try formFactorFavMigration.getFavoritesOrderFromPreV4Model(dbContainerLocation: BookmarkDatabase.defaultDBLocation, + dbFileURL: BookmarkDatabase.defaultDBFileURL) + BookmarkDatabase.shared.preFormFactorSpecificFavoritesFolderOrder = favoritesOrder + } catch { PixelKit.fire(DebugEvent(GeneralPixel.bookmarksCouldNotLoadDatabase(error: error))) Thread.sleep(forTimeInterval: 1) - fatalError("Could not create Bookmarks database stack: \(error?.localizedDescription ?? "err")") + fatalError("Could not create Bookmarks database stack: \(error.localizedDescription)") } - BookmarkDatabase.shared.preFormFactorSpecificFavoritesFolderOrder = BookmarkFormFactorFavoritesMigration - .getFavoritesOrderFromPreV4Model( - dbContainerLocation: BookmarkDatabase.defaultDBLocation, - dbFileURL: BookmarkDatabase.defaultDBFileURL, - errorEvents: preMigrationErrorHandling - ) - BookmarkDatabase.shared.db.loadStore { context, error in guard let context = context else { PixelKit.fire(DebugEvent(GeneralPixel.bookmarksCouldNotLoadDatabase(error: error))) diff --git a/DuckDuckGo/Bookmarks/Legacy/LegacyBookmarksStoreMigration.swift b/DuckDuckGo/Bookmarks/Legacy/LegacyBookmarksStoreMigration.swift index ad7cf4fc1c5..96a9b0fb6bc 100644 --- a/DuckDuckGo/Bookmarks/Legacy/LegacyBookmarksStoreMigration.swift +++ b/DuckDuckGo/Bookmarks/Legacy/LegacyBookmarksStoreMigration.swift @@ -66,7 +66,7 @@ public class LegacyBookmarksStoreMigration { _ = LegacyBookmarkStore(context: source) // Prepare destination - BookmarkUtils.prepareLegacyFoldersStructure(in: destination) + try? BookmarkUtils.prepareLegacyFoldersStructure(in: destination) guard let newRoot = BookmarkUtils.fetchRootFolder(destination), let newFavoritesRoot = BookmarkUtils.fetchLegacyFavoritesFolder(destination) else { @@ -163,7 +163,7 @@ public class LegacyBookmarksStoreMigration { } catch { destination.reset() - BookmarkUtils.prepareLegacyFoldersStructure(in: destination) + try? BookmarkUtils.prepareLegacyFoldersStructure(in: destination) do { try destination.save(onErrorFire: GeneralPixel.bookmarksMigrationCouldNotPrepareDatabaseOnFailedMigration) } catch { diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index 541a8544e50..0da0593983e 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "179.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0"), .package(path: "../SwiftUIExtensions"), .package(path: "../XPCHelper"), ], diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index 54476802517..841f8ef5eb5 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -32,7 +32,7 @@ let package = Package( .library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "179.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0"), .package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"), .package(path: "../AppLauncher"), .package(path: "../UDSHelper"), diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index 6f04c63220f..6e9ed1cd74a 100644 --- a/LocalPackages/SubscriptionUI/Package.swift +++ b/LocalPackages/SubscriptionUI/Package.swift @@ -12,7 +12,7 @@ let package = Package( targets: ["SubscriptionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "179.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0"), .package(path: "../SwiftUIExtensions") ], targets: [ From ab2e0ddddc125873e17237aacc28910409dd58fa Mon Sep 17 00:00:00 2001 From: Fernando Bunn Date: Mon, 5 Aug 2024 09:32:23 +0100 Subject: [PATCH 08/32] Add UI for displaying Duck Player contingency message (#3065) Task/Issue URL: https://app.asana.com/0/1204167627774280/1207870880420544/f **Description**: Add UI for displaying Duck Player contingency message --- .../WarningYoutube.imageset/Contents.json | 12 ++++ .../WarningYoutube.pdf | Bin 0 -> 3100 bytes DuckDuckGo/Common/Localizables/UserText.swift | 4 ++ DuckDuckGo/Localizable.xcstrings | 36 ++++++++++ .../Model/DuckPlayerPreferences.swift | 11 +++ .../View/PreferencesDuckPlayerView.swift | 64 ++++++++++++++++++ 6 files changed, 127 insertions(+) create mode 100644 DuckDuckGo/Assets.xcassets/Images/WarningYoutube.imageset/Contents.json create mode 100644 DuckDuckGo/Assets.xcassets/Images/WarningYoutube.imageset/WarningYoutube.pdf diff --git a/DuckDuckGo/Assets.xcassets/Images/WarningYoutube.imageset/Contents.json b/DuckDuckGo/Assets.xcassets/Images/WarningYoutube.imageset/Contents.json new file mode 100644 index 00000000000..01e3b61ed5d --- /dev/null +++ b/DuckDuckGo/Assets.xcassets/Images/WarningYoutube.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "WarningYoutube.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/DuckDuckGo/Assets.xcassets/Images/WarningYoutube.imageset/WarningYoutube.pdf b/DuckDuckGo/Assets.xcassets/Images/WarningYoutube.imageset/WarningYoutube.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2f251c69272d09f3e977e497f252f95a626e97e0 GIT binary patch literal 3100 zcmb7`c|6qX9>gyoAV>fK zP+UA90HCD>zzyBKKoXVp?nMAe`XnO7mBd_Z4f zkA%ekLN77ODm=#HRvaC;BEf$y{5Q(nbCvrim4gOGOs(9`j$yy#JS-&LMTYxHJ@9&?=yI#@&=Zqqw+a;x<8lTDtAgY5 zE{*jIC=1Lwi>4`xt3TQSYu?Wn4okb>#8ViDP^-*njA=UXiAHEU5Lk;C7nyT}$^_DN zbBEAeD($@H^o1pB_r(s*b&?-?()efddouEkBdJV2eYg6(B0SZOQcV4PFqM6ol%ai6 zk?AvLJieh#!@}_pkZ|b3c;P8WC@v@9*nPy8;D{Sf1XC*NaROvM0lDZaJ=~Jb%vKjJ z37)utKVo2U3qALy+dueyULCxjz4lY@m(`ouEBlwQ&(fc?&#m*g?e&x{Eg1gLvnTod z)Tz0ZM~7{@5`_k{hGNJ;$F(oh*8q4bS|RwteCq+`lhkQh0gZ*3muV$(-ltZdb(fFE zf}JgGlC3BOUG%~6xyruG9SM%7?V^mk@RCNK^CE=y=E#4xf$7@ue+-ExlnWmP=l7JQ zNgKy|*EQE&k2U%wz1I|(toHnv$X7LGi3UNBb7Xr7@qR_=D80GK#|*u9R8|ECvJvG8 zyjD|qqhHg;qZArLg9@skZzX#T%e^%-90L&iEpR@?7}fnS=skvZ=Z#laer*sGgh@F- zpEi24e6Cx;SoKrf%?(zw>!+(hu$pQ&s;xtWVrBg1A0y@tTJ-iQ<`qtSEza-q*E^6H zD(qVXp{Bk21v$Fe8tC5H6nOlW zw&SyFiNpNQKNZ`UbnUrOQ8iOrZCRG-@YULpQc)3DVyZV5^qURzS4e;@G$R))#f*+W zjY42s!-DVd#ElkVOyd3!6Pc?Yq@6a+_}Ax@Ml=wbBwPmuA0a=KHw~NSn!OQO&;O!B z2Cmv{oh=;QFjnpmEqGGa6q@PVl+602ad+=K$M=i;6U|*AV*Ya){=2Qn_*(b)iKQmd z8qDi-@8?rx9z1o5{gTRpk*?Q`8MiaC1ltm(N(+P+&p^|en#o3;Q#?X@DszM1kBU67 zra<#jgg*IOlxT~|$N1-z;Kk%+o(p3Aduc00XSFjmV=KI+No_lHY~P;cb!l#0Uzb#7 znASKmM@7~$5tF_nFKe>j@{LoL(G$Tj6J1Z&--tc1#=S0J7Mt5i1QU}+*RACOt$+Tu zo2mP6R9gGDIbsk{(psri!G}9#z;#->ff15zyWiR+2>3Sd6=t~dsWuI&a#VCCC5n!y zIPoq_QB;dDadlBoq@%10y1bjp^98BO+9EiPr=2IJ_w7>h6o`7d+guZ1>U4p#y zfgrk|N34GDC1<$u-L-dyZc4Tn_vl;7B((9PxbFEHoG6kUII5G=OxBIQe_kwd);@X1 zs>qw%*Y@ zE;f_L7fz_>_AVF55y93dk>y_%#X2kxU6Z$*_((UaOA1g;7)g8-XL?0t=wZVAE;yLC zFH(cpuH8MmS|=SY)gbMZnEQ2>EXxP(HYl272+pi}RE_M@98&Kj(RFLcz2y<21tlVw zxQDkEYWRWzc<&H-;oQTy-zbAB~|@Rar{<iXgH;(FOd zeK(oNkW=c$k09Jn5!wEo;8+>nhi6{S*8PkfzLZ;je^$T_xkz`q=5vLGftYumI@1A3 zt-YqD>bk@4CvG<#fsOKbXf*fHnH8f#9VZ3uK5jX(KWhEYV#v`Q2H9^+G;dBZYXAoL zsQEbF6cMAPuY9j>SBjozWG=>eS&H73Oul*9y3sR!_(}x$l-734{78=5f>0R#n4#+6 zg(DE)h{KF+ID_f!kyW;}^%%=1g`mm*q9N4!tad&0i6=0`e z1#DeekK)IQMgAiJ+6INTIELNk#LkfR{lFiY>k&YL7sYLRXdsnz7J>jYAsd|}`xQW= zQ0gdvC2tNS0^rO5pG^s=q0TyzJ^mu0SwP+{p-`+8w@GR!(57STSNdN!< literal 0 HcmV?d00001 diff --git a/DuckDuckGo/Common/Localizables/UserText.swift b/DuckDuckGo/Common/Localizables/UserText.swift index a56ddb51993..a9958fdba78 100644 --- a/DuckDuckGo/Common/Localizables/UserText.swift +++ b/DuckDuckGo/Common/Localizables/UserText.swift @@ -391,6 +391,10 @@ struct UserText { static let duckPlayerNewTabPreferenceExtraInfo = NSLocalizedString("duck-player.newtab.info-preference", value: "When browsing YouTube on the web", comment: "New tab preference extra info in settings") static let duckPlayerVideoPreferencesTitle = NSLocalizedString("duck-player.video-preferences-title", value: "Video Preferences", comment: "Video Preferences title in settings") + static let duckPlayerContingencyMessageTitle = NSLocalizedString("duck-player.contingency-title", value: "Duck Player Unavailable", comment: "Title for message explaining to the user that Duck Player is not available") + static let duckPlayerContingencyMessageBody = NSLocalizedString("duck-player.video-contingency-message", value: "Duck Player's functionality has been affected by recent changes to YouTube. We’re working to fix these issues and appreciate your understanding.", comment: "Message explaining to the user that Duck Player is not available") + static let duckPlayerContingencyMessageCTA = NSLocalizedString("duck-player.video-contingency-cta", value: "Learn More", comment: "Button for the message explaining to the user that Duck Player is not available so the user can learn more") + static let gpcCheckboxTitle = NSLocalizedString("gpc.checkbox.title", value: "Enable Global Privacy Control", comment: "GPC settings checkbox title") static let gpcExplanation = NSLocalizedString("gpc.explanation", value: "Tells participating websites not to sell or share your data.", comment: "GPC explanation in settings") diff --git a/DuckDuckGo/Localizable.xcstrings b/DuckDuckGo/Localizable.xcstrings index dc229ee8bb5..b21ce803f6d 100644 --- a/DuckDuckGo/Localizable.xcstrings +++ b/DuckDuckGo/Localizable.xcstrings @@ -17381,6 +17381,18 @@ } } }, + "duck-player.contingency-title" : { + "comment" : "Title for message explaining to the user that Duck Player is not available", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Duck Player Unavailable" + } + } + } + }, "duck-player.explanation" : { "comment" : "Private YouTube Player explanation in settings", "extractionState" : "extracted_with_value", @@ -17801,6 +17813,30 @@ } } }, + "duck-player.video-contingency-cta" : { + "comment" : "Button for the message explaining to the user that Duck Player is not available so the user can learn more", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Learn More" + } + } + } + }, + "duck-player.video-contingency-message" : { + "comment" : "Message explaining to the user that Duck Player is not available", + "extractionState" : "extracted_with_value", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Duck Player's functionality has been affected by recent changes to YouTube. We’re working to fix these issues and appreciate your understanding." + } + } + } + }, "duck-player.video-preferences-title" : { "comment" : "Video Preferences title in settings", "extractionState" : "extracted_with_value", diff --git a/DuckDuckGo/Preferences/Model/DuckPlayerPreferences.swift b/DuckDuckGo/Preferences/Model/DuckPlayerPreferences.swift index ef6ca9fc389..00be35f086f 100644 --- a/DuckDuckGo/Preferences/Model/DuckPlayerPreferences.swift +++ b/DuckDuckGo/Preferences/Model/DuckPlayerPreferences.swift @@ -111,6 +111,17 @@ final class DuckPlayerPreferences: ObservableObject { } } + var shouldDisplayContingencyMessage: Bool { + false + } + + @MainActor + func openLearnMoreContingencyURL() { + #warning("DuckPlayer - Replace this with real URL") + guard let url = URL(string: "https://duckduckgo.com/duckduckgo-help-pages/duck-player/") else { return } + WindowControllersManager.shared.show(url: url, source: .ui, newTab: true) + } + init(persistor: DuckPlayerPreferencesPersistor = DuckPlayerPreferencesUserDefaultsPersistor(), privacyConfigurationManager: PrivacyConfigurationManaging = ContentBlocking.shared.privacyConfigurationManager, internalUserDecider: InternalUserDecider = NSApp.delegateTyped.internalUserDecider) { diff --git a/DuckDuckGo/Preferences/View/PreferencesDuckPlayerView.swift b/DuckDuckGo/Preferences/View/PreferencesDuckPlayerView.swift index 46305daebed..12e6209597e 100644 --- a/DuckDuckGo/Preferences/View/PreferencesDuckPlayerView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesDuckPlayerView.swift @@ -48,6 +48,15 @@ extension Preferences { // TITLE TextMenuTitle(UserText.duckPlayer) + if model.shouldDisplayContingencyMessage { + PreferencePaneSection { + ContingencyMessageView { + model.openLearnMoreContingencyURL() + } + .frame(width: 512) + } + } + PreferencePaneSection { Picker(selection: duckPlayerModeBinding, content: { Text(UserText.duckPlayerAlwaysOpenInPlayer) @@ -87,3 +96,58 @@ extension Preferences { } } } + +private struct ContingencyMessageView: View { + private enum Copy { + static let title: String = UserText.duckPlayerContingencyMessageTitle + static let message: String = UserText.duckPlayerContingencyMessageBody + static let buttonTitle: String = UserText.duckPlayerContingencyMessageCTA + } + + private enum Constants { + static let cornerRadius: CGFloat = 8 + static let imageName: String = "WarningYoutube" + static let imageSize: CGSize = CGSize(width: 64, height: 48) + } + + let buttonCallback: () -> Void + + var body: some View { + HStack(alignment: .top, spacing: 20) { + Image(Constants.imageName) + .resizable() + .aspectRatio(contentMode: .fit) + .frame(width: Constants.imageSize.width, height: Constants.imageSize.height) + + VStack (alignment: .leading, spacing: 3) { + Text(Copy.title) + .bold() + Text(Copy.message) + .foregroundColor(Color(.blackWhite60)) + .multilineTextAlignment(.leading) + .lineLimit(nil) + .fixedSize(horizontal: false, vertical: true) + Button { + buttonCallback() + } label: { + Text(Copy.buttonTitle) + }.padding(.top, 15) + } + } + .padding() + .background( + ZStack { + RoundedRectangle(cornerRadius: Constants.cornerRadius) + .stroke(Color(.blackWhite10), lineWidth: 1) + RoundedRectangle(cornerRadius: Constants.cornerRadius) + .fill(Color(.blackWhite1)) + } + ) + } +} + +#Preview { + Group { + ContingencyMessageView { } + }.frame(height: 300) +} From 9a32b78ebc52d9b13f2edcf1f52c568cbe9a564f Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Mon, 5 Aug 2024 11:27:37 +0200 Subject: [PATCH 09/32] Removes the VPN bouncer (#3066) Task/Issue URL: https://app.asana.com/0/1207603085593419/1207850681305772/f ## Description Removes the VPN bouncer. --- DuckDuckGo.xcodeproj/project.pbxproj | 6 -- DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift | 13 +---- DuckDuckGoVPN/NetworkProtectionBouncer.swift | 60 -------------------- 3 files changed, 3 insertions(+), 76 deletions(-) delete mode 100644 DuckDuckGoVPN/NetworkProtectionBouncer.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 4efd45bc80e..4c86d42ff33 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -1600,8 +1600,6 @@ 7BA7CC3E2AD11E380042E5CE /* TunnelControllerIPCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA7CC112AD11DC80042E5CE /* TunnelControllerIPCService.swift */; }; 7BA7CC3F2AD11E3D0042E5CE /* AppLauncher+DefaultInitializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA7CC132AD11DC80042E5CE /* AppLauncher+DefaultInitializer.swift */; }; 7BA7CC402AD11E3D0042E5CE /* AppLauncher+DefaultInitializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA7CC132AD11DC80042E5CE /* AppLauncher+DefaultInitializer.swift */; }; - 7BA7CC412AD11E420042E5CE /* NetworkProtectionBouncer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA7CC152AD11DC80042E5CE /* NetworkProtectionBouncer.swift */; }; - 7BA7CC422AD11E420042E5CE /* NetworkProtectionBouncer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA7CC152AD11DC80042E5CE /* NetworkProtectionBouncer.swift */; }; 7BA7CC432AD11E480042E5CE /* UserText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA7CC172AD11DC80042E5CE /* UserText.swift */; }; 7BA7CC442AD11E490042E5CE /* UserText.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA7CC172AD11DC80042E5CE /* UserText.swift */; }; 7BA7CC472AD11E5C0042E5CE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7BA7CC122AD11DC80042E5CE /* Assets.xcassets */; }; @@ -3532,7 +3530,6 @@ 7BA7CC122AD11DC80042E5CE /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 7BA7CC132AD11DC80042E5CE /* AppLauncher+DefaultInitializer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AppLauncher+DefaultInitializer.swift"; sourceTree = ""; }; 7BA7CC142AD11DC80042E5CE /* DuckDuckGoVPNAppStore.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = DuckDuckGoVPNAppStore.entitlements; sourceTree = ""; }; - 7BA7CC152AD11DC80042E5CE /* NetworkProtectionBouncer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkProtectionBouncer.swift; sourceTree = ""; }; 7BA7CC162AD11DC80042E5CE /* DuckDuckGoVPN.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = DuckDuckGoVPN.entitlements; sourceTree = ""; }; 7BA7CC172AD11DC80042E5CE /* UserText.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UserText.swift; sourceTree = ""; }; 7BA7CC182AD11DC80042E5CE /* DuckDuckGoVPNDebug.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = DuckDuckGoVPNDebug.entitlements; sourceTree = ""; }; @@ -6135,7 +6132,6 @@ 7BA7CC0E2AD11DC80042E5CE /* DuckDuckGoVPNAppDelegate.swift */, 7BD1688D2AD4A4C400D24876 /* NetworkExtensionController.swift */, EEDE50102BA360C80017F3C4 /* NetworkProtection+VPNAgentConvenienceInitializers.swift */, - 7BA7CC152AD11DC80042E5CE /* NetworkProtectionBouncer.swift */, 7B8DB3192B504D7500EC16DA /* VPNAppEventsHandler.swift */, 7B0694972B6E980F00FA4DBA /* VPNProxyLauncher.swift */, EE34245D2BA0853900173B1B /* VPNUninstaller.swift */, @@ -11087,7 +11083,6 @@ 7BA7CC442AD11E490042E5CE /* UserText.swift in Sources */, 4BF0E5142AD25A2600FFEC9E /* DuckDuckGoUserAgent.swift in Sources */, F1FDC93C2BF51F41006B1435 /* VPNSettings+Environment.swift in Sources */, - 7BA7CC422AD11E420042E5CE /* NetworkProtectionBouncer.swift in Sources */, B65DA5F12A77D2BC00CBEE8D /* BundleExtension.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -11108,7 +11103,6 @@ F1D0429E2BFBABA100A31506 /* SubscriptionManager+StandardConfiguration.swift in Sources */, 7BA7CC3F2AD11E3D0042E5CE /* AppLauncher+DefaultInitializer.swift in Sources */, 4B0EF7292B5780EB009D6481 /* VPNAppEventsHandler.swift in Sources */, - 7BA7CC412AD11E420042E5CE /* NetworkProtectionBouncer.swift in Sources */, 4BF0E5082AD2551A00FFEC9E /* NetworkProtectionPixelEvent.swift in Sources */, 7BA7CC582AD1203A0042E5CE /* UserText+NetworkProtection.swift in Sources */, 7BA7CC4B2AD11EC60042E5CE /* NetworkProtectionControllerErrorStore.swift in Sources */, diff --git a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift index a6d828b95f0..6a3e6c6f7f5 100644 --- a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift +++ b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift @@ -66,8 +66,7 @@ final class DuckDuckGoVPNApplication: NSApplication { subscriptionEndpointService: subscriptionEndpointService, authEndpointService: authEndpointService) - _delegate = DuckDuckGoVPNAppDelegate(bouncer: NetworkProtectionBouncer(accountManager: accountManager), - accountManager: accountManager, + _delegate = DuckDuckGoVPNAppDelegate(accountManager: accountManager, accessTokenStorage: accessTokenStorage, subscriptionEnvironment: subscriptionEnvironment) super.init() @@ -130,15 +129,13 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { private static let recentThreshold: TimeInterval = 5.0 private let appLauncher = AppLauncher() - private let bouncer: NetworkProtectionBouncer private let accountManager: AccountManager private let accessTokenStorage: SubscriptionTokenKeychainStorage - public init(bouncer: NetworkProtectionBouncer, - accountManager: AccountManager, + public init(accountManager: AccountManager, accessTokenStorage: SubscriptionTokenKeychainStorage, subscriptionEnvironment: SubscriptionEnvironment) { - self.bouncer = bouncer + self.accountManager = accountManager self.accessTokenStorage = accessTokenStorage self.tunnelSettings = VPNSettings(defaults: .netP) @@ -365,10 +362,6 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { setupMenuVisibility() Task { @MainActor in - // The reason we want to await for this is that nothing else should be executed - // if the app should quit. - await bouncer.requireAuthTokenOrKillApp(controller: tunnelController) - // Initialize lazy properties _ = tunnelControllerIPCService _ = vpnProxyLauncher diff --git a/DuckDuckGoVPN/NetworkProtectionBouncer.swift b/DuckDuckGoVPN/NetworkProtectionBouncer.swift deleted file mode 100644 index 537d7cadcaf..00000000000 --- a/DuckDuckGoVPN/NetworkProtectionBouncer.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// NetworkProtectionBouncer.swift -// -// Copyright © 2023 DuckDuckGo. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Common -import Foundation -import NetworkProtection -import ServiceManagement -import AppKit -import Subscription - -/// Class that implements the necessary logic to ensure the VPN is enabled, or prevent the app from running otherwise. -/// -final class NetworkProtectionBouncer { - - let accountManager: AccountManager - - init(accountManager: AccountManager) { - self.accountManager = accountManager - } - - /// Simply verifies that the VPN feature is enabled and if not, takes care of killing the - /// current app. - /// - func requireAuthTokenOrKillApp(controller: TunnelController) async { - guard !accountManager.isUserAuthenticated else { - return - } - - let keychainStore = NetworkProtectionKeychainTokenStore(keychainType: .default, - errorEvents: nil, - isSubscriptionEnabled: false, - accessTokenProvider: { nil }) - guard keychainStore.isFeatureActivated else { - os_log(.error, log: .networkProtection, "🔴 Stopping: DuckDuckGo VPN not authorized. Missing token.") - - await controller.stop() - - // EXIT_SUCCESS ensures the login item won't relaunch - // Ref: https://developer.apple.com/documentation/servicemanagement/smappservice/register() - // See where it mentions: - // "If the helper crashes or exits with a non-zero status, the system relaunches it" - exit(EXIT_SUCCESS) - } - } -} From ec4b2d8331c790fdafaf0479cfe39f2e04f79df3 Mon Sep 17 00:00:00 2001 From: Michal Smaga Date: Mon, 5 Aug 2024 14:16:02 +0200 Subject: [PATCH 10/32] Return App Store subscription options only if not nil (#3068) Task/Issue URL: https://app.asana.com/0/1203936086921904/1207934463147478/f **Description**: In case no App Store subscription objects are available we should return a proper `SubscriptionOptions.empty` object. --- .../SubscriptionPagesUseSubscriptionFeature.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/DuckDuckGo/Tab/UserScripts/Subscription/SubscriptionPagesUseSubscriptionFeature.swift b/DuckDuckGo/Tab/UserScripts/Subscription/SubscriptionPagesUseSubscriptionFeature.swift index ad14f0ac86f..2251e93e27b 100644 --- a/DuckDuckGo/Tab/UserScripts/Subscription/SubscriptionPagesUseSubscriptionFeature.swift +++ b/DuckDuckGo/Tab/UserScripts/Subscription/SubscriptionPagesUseSubscriptionFeature.swift @@ -151,7 +151,9 @@ final class SubscriptionPagesUseSubscriptionFeature: Subfeature { switch subscriptionPlatform { case .appStore: if #available(macOS 12.0, *) { - return await subscriptionManager.storePurchaseManager().subscriptionOptions() + if let subscriptionOptions = await subscriptionManager.storePurchaseManager().subscriptionOptions() { + return subscriptionOptions + } } case .stripe: switch await stripePurchaseFlow.subscriptionOptions() { From 7ceababdb40a1695f23efca241efb435c1e7365c Mon Sep 17 00:00:00 2001 From: Dax the Duck Date: Mon, 5 Aug 2024 13:06:11 +0000 Subject: [PATCH 11/32] Update embedded files --- .../AppPrivacyConfigurationDataProvider.swift | 4 +- .../AppTrackerDataSetProvider.swift | 4 +- DuckDuckGo/ContentBlocker/macos-config.json | 22 +- DuckDuckGo/ContentBlocker/trackerData.json | 13295 +++++++++++++--- 4 files changed, 11098 insertions(+), 2227 deletions(-) diff --git a/DuckDuckGo/ContentBlocker/AppPrivacyConfigurationDataProvider.swift b/DuckDuckGo/ContentBlocker/AppPrivacyConfigurationDataProvider.swift index d3c1c91f4a4..1952489e649 100644 --- a/DuckDuckGo/ContentBlocker/AppPrivacyConfigurationDataProvider.swift +++ b/DuckDuckGo/ContentBlocker/AppPrivacyConfigurationDataProvider.swift @@ -22,8 +22,8 @@ import BrowserServicesKit final class AppPrivacyConfigurationDataProvider: EmbeddedDataProvider { public struct Constants { - public static let embeddedDataETag = "\"6403cfec3fc0fdc8bd9d3967c4d93c70\"" - public static let embeddedDataSHA = "331ccf1c2918df4510481778abc742cd88e453fa7366dda45a747920c901f86a" + public static let embeddedDataETag = "\"d18a43dc49166bc0411e373d07749097\"" + public static let embeddedDataSHA = "13f1729535254a1645601eb4b90d067ab0ac390efff908b2565b06580a832237" } var embeddedDataEtag: String { diff --git a/DuckDuckGo/ContentBlocker/AppTrackerDataSetProvider.swift b/DuckDuckGo/ContentBlocker/AppTrackerDataSetProvider.swift index e47ae7d39a2..eb0eddd21d9 100644 --- a/DuckDuckGo/ContentBlocker/AppTrackerDataSetProvider.swift +++ b/DuckDuckGo/ContentBlocker/AppTrackerDataSetProvider.swift @@ -22,8 +22,8 @@ import BrowserServicesKit final class AppTrackerDataSetProvider: EmbeddedDataProvider { public struct Constants { - public static let embeddedDataETag = "\"6fa664462bd29b66c1b13eed51072afa\"" - public static let embeddedDataSHA = "52d29aa8942e518db24a5adbcca63148aac9c01a8a28c3f2c4bc517cb80b18ff" + public static let embeddedDataETag = "\"1d2c4aaf7c97f8262ea54b7ca24265b2\"" + public static let embeddedDataSHA = "4f91db9771dc0ba63741bdb2ab953b46a12f1ef11b59e389142f1e3c151f3a01" } var embeddedDataEtag: String { diff --git a/DuckDuckGo/ContentBlocker/macos-config.json b/DuckDuckGo/ContentBlocker/macos-config.json index e129950d989..1d521ae7035 100644 --- a/DuckDuckGo/ContentBlocker/macos-config.json +++ b/DuckDuckGo/ContentBlocker/macos-config.json @@ -1,6 +1,6 @@ { "readme": "https://github.com/duckduckgo/privacy-configuration", - "version": 1722257174026, + "version": 1722602607085, "features": { "adClickAttribution": { "readme": "https://help.duckduckgo.com/duckduckgo-help-pages/privacy/web-tracking-protections/#3rd-party-tracker-loading-protection", @@ -1938,6 +1938,7 @@ "ad feedback", "annonse", "anzeige", + "close", "close ad", "close this ad", "content continues below", @@ -2106,6 +2107,15 @@ } ] }, + { + "domain": "asuracomic.net", + "rules": [ + { + "selector": ".h12container", + "type": "hide" + } + ] + }, { "domain": "avito.ru", "rules": [ @@ -2515,10 +2525,18 @@ "selector": ".topbanner-wrap", "type": "hide" }, + { + "selector": ".display-ad-leaderboard", + "type": "hide-empty" + }, { "selector": ".display-ad-wrapper", "type": "hide-empty" }, + { + "selector": ".display-ad-wrap", + "type": "hide-empty" + }, { "selector": "[id*='ddc-sidebox-ad-stacked-wrap']", "type": "hide-empty" @@ -4648,7 +4666,7 @@ ] }, "state": "enabled", - "hash": "4689e9dd3357db39d086b254fb00507f" + "hash": "4540ef2182cc5c1a82008606b63a1cbd" }, "exceptionHandler": { "exceptions": [ diff --git a/DuckDuckGo/ContentBlocker/trackerData.json b/DuckDuckGo/ContentBlocker/trackerData.json index 7a12422f7a8..b8c0af55dcd 100644 --- a/DuckDuckGo/ContentBlocker/trackerData.json +++ b/DuckDuckGo/ContentBlocker/trackerData.json @@ -1,6 +1,6 @@ { "_builtWith": { - "tracker-radar": "9c02278e8bfb43db5e6b8756cdedc469924d600b8c4d6c9d7177de01405c8f5c-4013b4e91930c643394cb31c6c745356f133b04f", + "tracker-radar": "c1a08eeb146b1dc8cd87c026df746b567b36177d4eb7cff42d7724cf49d8a2b2-4013b4e91930c643394cb31c6c745356f133b04f", "tracker-surrogates": "0528e3226df15b1a3e319ad68ef76612a8f26623" }, "readme": "https://github.com/duckduckgo/tracker-blocklists", @@ -434,7 +434,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -445,7 +445,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -491,7 +491,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -2379,7 +2379,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -2390,7 +2390,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -2434,7 +2434,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -2445,7 +2445,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -2560,7 +2560,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -2694,7 +2694,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -2705,7 +2705,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -3024,7 +3024,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -3151,7 +3151,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -3275,7 +3275,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -3659,7 +3659,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -3670,7 +3670,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -3681,7 +3681,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -3692,7 +3692,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -3758,7 +3758,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -3810,7 +3810,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -3821,7 +3821,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -3958,7 +3958,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -4309,7 +4309,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -4344,7 +4344,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -4790,7 +4790,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -4801,7 +4801,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5003,7 +5003,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5045,7 +5045,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5068,7 +5068,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5103,7 +5103,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5132,7 +5132,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5420,7 +5420,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5537,7 +5537,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5548,7 +5548,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5559,7 +5559,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5570,7 +5570,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5607,7 +5607,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -5662,7 +5662,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -6198,7 +6198,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -6352,7 +6352,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -6668,7 +6668,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -6679,7 +6679,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -6799,7 +6799,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -6995,7 +6995,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -7031,7 +7031,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -7042,7 +7042,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -7053,7 +7053,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -7664,7 +7664,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -7675,7 +7675,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -7686,7 +7686,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -7767,7 +7767,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -7890,7 +7890,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -7901,7 +7901,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -7979,7 +7979,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -7990,7 +7990,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -8105,7 +8105,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -8256,7 +8256,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -8267,7 +8267,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -8758,7 +8758,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -8769,7 +8769,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -8810,7 +8810,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -9226,7 +9226,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -9824,7 +9824,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -9835,7 +9835,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -9846,7 +9846,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -9886,7 +9886,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -9928,7 +9928,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -9982,7 +9982,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -10050,7 +10050,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -10061,7 +10061,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -10109,7 +10109,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -10235,7 +10235,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -10395,7 +10395,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -10406,7 +10406,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -10417,7 +10417,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -10444,7 +10444,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -10494,7 +10494,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -10541,7 +10541,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -11019,7 +11019,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -11059,7 +11059,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -11795,7 +11795,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -11884,7 +11884,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -11895,7 +11895,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -12092,7 +12092,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -12132,7 +12132,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -12143,7 +12143,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -12154,7 +12154,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -12165,7 +12165,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -12491,7 +12491,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -12502,7 +12502,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -12513,7 +12513,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -14421,7 +14421,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -15106,7 +15106,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -15181,7 +15181,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -15232,7 +15232,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -16091,7 +16091,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -16102,7 +16102,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -16131,7 +16131,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -16350,7 +16350,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -16659,7 +16659,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -16670,7 +16670,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -16855,7 +16855,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -16904,7 +16904,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -17178,7 +17178,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -17189,7 +17189,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -17752,7 +17752,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -18100,7 +18100,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -18239,7 +18239,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -18598,7 +18598,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -18809,7 +18809,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -19986,7 +19986,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -20207,7 +20207,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -20218,7 +20218,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -20229,7 +20229,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -20369,7 +20369,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -20856,7 +20856,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -20885,7 +20885,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -20896,7 +20896,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -20907,7 +20907,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -20971,7 +20971,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21051,7 +21051,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21099,7 +21099,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21110,7 +21110,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21150,7 +21150,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21161,7 +21161,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21196,7 +21196,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21207,7 +21207,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21340,7 +21340,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21424,7 +21424,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21895,7 +21895,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21906,7 +21906,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21917,7 +21917,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21987,7 +21987,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -21998,7 +21998,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22151,7 +22151,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22162,7 +22162,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22204,7 +22204,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22215,7 +22215,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22226,7 +22226,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22496,7 +22496,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22507,7 +22507,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22568,7 +22568,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22626,7 +22626,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22637,7 +22637,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22737,7 +22737,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22760,7 +22760,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -22771,7 +22771,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23128,7 +23128,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23232,7 +23232,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23368,7 +23368,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23443,7 +23443,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23454,7 +23454,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23498,7 +23498,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23509,7 +23509,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23520,7 +23520,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23531,7 +23531,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23611,7 +23611,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23644,7 +23644,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23695,7 +23695,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23831,7 +23831,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23960,7 +23960,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -23971,7 +23971,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24218,7 +24218,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24229,7 +24229,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24240,7 +24240,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24521,7 +24521,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24556,7 +24556,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24597,7 +24597,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24713,7 +24713,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24724,7 +24724,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24753,7 +24753,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24849,7 +24849,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24906,7 +24906,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -24917,7 +24917,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25038,7 +25038,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25195,7 +25195,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25221,7 +25221,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25232,7 +25232,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25295,7 +25295,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25306,7 +25306,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25317,7 +25317,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25548,7 +25548,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25575,7 +25575,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25586,7 +25586,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25597,7 +25597,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25627,7 +25627,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25638,7 +25638,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25666,7 +25666,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25677,7 +25677,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25750,7 +25750,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25798,7 +25798,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25809,7 +25809,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25820,7 +25820,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25831,7 +25831,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25842,7 +25842,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25853,7 +25853,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25925,7 +25925,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25936,7 +25936,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -25990,7 +25990,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -26192,7 +26192,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -26500,7 +26500,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -26511,7 +26511,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -26522,7 +26522,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -26773,7 +26773,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -26784,7 +26784,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -27202,7 +27202,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -28059,7 +28059,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -28208,7 +28208,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -28219,7 +28219,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -28352,7 +28352,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -28435,7 +28435,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -28446,7 +28446,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -28807,7 +28807,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -29133,7 +29133,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -29144,7 +29144,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -29270,7 +29270,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -29281,7 +29281,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -31055,7 +31055,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -31398,7 +31398,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -32552,7317 +32552,14786 @@ "rules": [], "default": "block" }, - "4jnzhl0d0.com": { - "domain": "4jnzhl0d0.com", + "2znp09oa.com": { + "domain": "2znp09oa.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "aboardamusement.com": { - "domain": "aboardamusement.com", + "4jnzhl0d0.com": { + "domain": "4jnzhl0d0.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "aboardlevel.com": { - "domain": "aboardlevel.com", + "5mcwl.pw": { + "domain": "5mcwl.pw", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "absentairport.com": { - "domain": "absentairport.com", + "6ldu6qa.com": { + "domain": "6ldu6qa.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "absorbingcorn.com": { - "domain": "absorbingcorn.com", + "82o9v830.com": { + "domain": "82o9v830.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "abstractedamount.com": { - "domain": "abstractedamount.com", + "abilityscale.com": { + "domain": "abilityscale.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "acceptableauthority.com": { - "domain": "acceptableauthority.com", + "aboardamusement.com": { + "domain": "aboardamusement.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "accurateanimal.com": { - "domain": "accurateanimal.com", + "aboardlevel.com": { + "domain": "aboardlevel.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "accuratecoal.com": { - "domain": "accuratecoal.com", + "abovechat.com": { + "domain": "abovechat.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "actoramusement.com": { - "domain": "actoramusement.com", + "abruptroad.com": { + "domain": "abruptroad.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "actuallysnake.com": { - "domain": "actuallysnake.com", + "absentairport.com": { + "domain": "absentairport.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "actuallything.com": { - "domain": "actuallything.com", + "absorbingcorn.com": { + "domain": "absorbingcorn.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "adamantsnail.com": { - "domain": "adamantsnail.com", + "absorbingprison.com": { + "domain": "absorbingprison.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "adorableanger.com": { - "domain": "adorableanger.com", + "abstractedamount.com": { + "domain": "abstractedamount.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "adorableattention.com": { - "domain": "adorableattention.com", + "absurdapple.com": { + "domain": "absurdapple.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "adventurousamount.com": { - "domain": "adventurousamount.com", + "abundantcoin.com": { + "domain": "abundantcoin.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "agilebreeze.com": { - "domain": "agilebreeze.com", + "acceptableauthority.com": { + "domain": "acceptableauthority.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "agreeablearch.com": { - "domain": "agreeablearch.com", + "accurateanimal.com": { + "domain": "accurateanimal.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "agreeabletouch.com": { - "domain": "agreeabletouch.com", + "accuratecoal.com": { + "domain": "accuratecoal.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "aheadday.com": { - "domain": "aheadday.com", + "achieverknee.com": { + "domain": "achieverknee.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "alertarithmetic.com": { - "domain": "alertarithmetic.com", + "acidicstraw.com": { + "domain": "acidicstraw.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "aliasanvil.com": { - "domain": "aliasanvil.com", + "acridangle.com": { + "domain": "acridangle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ambientdusk.com": { - "domain": "ambientdusk.com", + "acridtwist.com": { + "domain": "acridtwist.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ambientlagoon.com": { - "domain": "ambientlagoon.com", + "actoramusement.com": { + "domain": "actoramusement.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ambiguousdinosaurs.com": { - "domain": "ambiguousdinosaurs.com", + "actuallysheep.com": { + "domain": "actuallysheep.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ambrosialsummit.com": { - "domain": "ambrosialsummit.com", + "actuallysnake.com": { + "domain": "actuallysnake.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "amethystzenith.com": { - "domain": "amethystzenith.com", + "actuallything.com": { + "domain": "actuallything.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "amuckafternoon.com": { - "domain": "amuckafternoon.com", + "adamantsnail.com": { + "domain": "adamantsnail.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "amusedbucket.com": { - "domain": "amusedbucket.com", + "addictedattention.com": { + "domain": "addictedattention.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "analyzecorona.com": { - "domain": "analyzecorona.com", + "admiral.pub": { + "domain": "admiral.pub", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ancientact.com": { - "domain": "ancientact.com", + "adorableanger.com": { + "domain": "adorableanger.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "annoyingacoustics.com": { - "domain": "annoyingacoustics.com", + "adorableattention.com": { + "domain": "adorableattention.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "aquaticowl.com": { - "domain": "aquaticowl.com", + "adventurousamount.com": { + "domain": "adventurousamount.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "arrivegrowth.com": { - "domain": "arrivegrowth.com", + "afraidlanguage.com": { + "domain": "afraidlanguage.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "aspiringapples.com": { - "domain": "aspiringapples.com", + "aftermathbrother.com": { + "domain": "aftermathbrother.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "astonishingfood.com": { - "domain": "astonishingfood.com", + "agilebreeze.com": { + "domain": "agilebreeze.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "audioarctic.com": { - "domain": "audioarctic.com", + "agreeablearch.com": { + "domain": "agreeablearch.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "automaticturkey.com": { - "domain": "automaticturkey.com", + "agreeabletouch.com": { + "domain": "agreeabletouch.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "awarealley.com": { - "domain": "awarealley.com", + "aheadday.com": { + "domain": "aheadday.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "awesomeagreement.com": { - "domain": "awesomeagreement.com", + "aheadgrow.com": { + "domain": "aheadgrow.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "awzbijw.com": { - "domain": "awzbijw.com", + "aheadmachine.com": { + "domain": "aheadmachine.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "axiomaticanger.com": { - "domain": "axiomaticanger.com", + "ak0gsh40.com": { + "domain": "ak0gsh40.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "badgeboat.com": { - "domain": "badgeboat.com", + "alertarithmetic.com": { + "domain": "alertarithmetic.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "badgerabbit.com": { - "domain": "badgerabbit.com", + "aliasanvil.com": { + "domain": "aliasanvil.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "baitbaseball.com": { - "domain": "baitbaseball.com", + "alleythecat.com": { + "domain": "alleythecat.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "balloonbelieve.com": { - "domain": "balloonbelieve.com", + "aloofmetal.com": { + "domain": "aloofmetal.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "barbarousbase.com": { - "domain": "barbarousbase.com", + "alpineactor.com": { + "domain": "alpineactor.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "basketballbelieve.com": { - "domain": "basketballbelieve.com", + "ambientdusk.com": { + "domain": "ambientdusk.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "beamvolcano.com": { - "domain": "beamvolcano.com", + "ambientlagoon.com": { + "domain": "ambientlagoon.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "beancontrol.com": { - "domain": "beancontrol.com", + "ambiguousanger.com": { + "domain": "ambiguousanger.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "begintrain.com": { - "domain": "begintrain.com", + "ambiguousdinosaurs.com": { + "domain": "ambiguousdinosaurs.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "bestboundary.com": { - "domain": "bestboundary.com", + "ambiguousincome.com": { + "domain": "ambiguousincome.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "bikesboard.com": { - "domain": "bikesboard.com", + "ambrosialsummit.com": { + "domain": "ambrosialsummit.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "birthdaybelief.com": { - "domain": "birthdaybelief.com", + "amethystzenith.com": { + "domain": "amethystzenith.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "blackbrake.com": { - "domain": "blackbrake.com", + "amuckafternoon.com": { + "domain": "amuckafternoon.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "bleachbubble.com": { - "domain": "bleachbubble.com", + "amusedbucket.com": { + "domain": "amusedbucket.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "blesspizzas.com": { - "domain": "blesspizzas.com", + "analogwonder.com": { + "domain": "analogwonder.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "blissfullagoon.com": { - "domain": "blissfullagoon.com", + "analyzecorona.com": { + "domain": "analyzecorona.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "blushingbeast.com": { - "domain": "blushingbeast.com", + "ancientact.com": { + "domain": "ancientact.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "boredcrown.com": { - "domain": "boredcrown.com", + "annoyingacoustics.com": { + "domain": "annoyingacoustics.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "boundarybusiness.com": { - "domain": "boundarybusiness.com", + "anxiousapples.com": { + "domain": "anxiousapples.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "boundlessveil.com": { - "domain": "boundlessveil.com", + "aquaticowl.com": { + "domain": "aquaticowl.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "brainybasin.com": { - "domain": "brainybasin.com", + "ar1nvz5.com": { + "domain": "ar1nvz5.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "brainynut.com": { - "domain": "brainynut.com", + "archswimming.com": { + "domain": "archswimming.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "branchborder.com": { - "domain": "branchborder.com", + "aromamirror.com": { + "domain": "aromamirror.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "bravecalculator.com": { - "domain": "bravecalculator.com", + "arrivegrowth.com": { + "domain": "arrivegrowth.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "breadbalance.com": { - "domain": "breadbalance.com", + "artthevoid.com": { + "domain": "artthevoid.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "breakfastboat.com": { - "domain": "breakfastboat.com", + "aspiringapples.com": { + "domain": "aspiringapples.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "brighttoe.com": { - "domain": "brighttoe.com", + "aspiringtoy.com": { + "domain": "aspiringtoy.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "briskstorm.com": { - "domain": "briskstorm.com", + "astonishingfood.com": { + "domain": "astonishingfood.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "broadborder.com": { - "domain": "broadborder.com", + "astralhustle.com": { + "domain": "astralhustle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "brotherslocket.com": { - "domain": "brotherslocket.com", + "astrallullaby.com": { + "domain": "astrallullaby.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "buildingknife.com": { - "domain": "buildingknife.com", + "attendchase.com": { + "domain": "attendchase.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "bulbbait.com": { - "domain": "bulbbait.com", + "attractivecap.com": { + "domain": "attractivecap.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "burlywhistle.com": { - "domain": "burlywhistle.com", + "audioarctic.com": { + "domain": "audioarctic.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "burnbubble.com": { - "domain": "burnbubble.com", + "automaticturkey.com": { + "domain": "automaticturkey.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "bushesbag.com": { - "domain": "bushesbag.com", + "availablerest.com": { + "domain": "availablerest.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "bustlingbath.com": { - "domain": "bustlingbath.com", + "avalonalbum.com": { + "domain": "avalonalbum.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "bustlingbook.com": { - "domain": "bustlingbook.com", + "averageactivity.com": { + "domain": "averageactivity.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "calculatingcircle.com": { - "domain": "calculatingcircle.com", + "awarealley.com": { + "domain": "awarealley.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "callousbrake.com": { - "domain": "callousbrake.com", + "awesomeagreement.com": { + "domain": "awesomeagreement.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "calmcactus.com": { - "domain": "calmcactus.com", + "awzbijw.com": { + "domain": "awzbijw.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "calypsocapsule.com": { - "domain": "calypsocapsule.com", + "axiomaticalley.com": { + "domain": "axiomaticalley.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "capriciouscorn.com": { - "domain": "capriciouscorn.com", + "axiomaticanger.com": { + "domain": "axiomaticanger.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "captivatingcanyon.com": { - "domain": "captivatingcanyon.com", + "azuremystique.com": { + "domain": "azuremystique.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "carefuldolls.com": { - "domain": "carefuldolls.com", + "backupcat.com": { + "domain": "backupcat.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "caringcast.com": { - "domain": "caringcast.com", + "badgeboat.com": { + "domain": "badgeboat.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cartkitten.com": { - "domain": "cartkitten.com", + "badgerabbit.com": { + "domain": "badgerabbit.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "catalogcake.com": { - "domain": "catalogcake.com", + "baitbaseball.com": { + "domain": "baitbaseball.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "catschickens.com": { - "domain": "catschickens.com", + "balloonbelieve.com": { + "domain": "balloonbelieve.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "causecherry.com": { - "domain": "causecherry.com", + "bananabarrel.com": { + "domain": "bananabarrel.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cautiouscamera.com": { - "domain": "cautiouscamera.com", + "barbarousbase.com": { + "domain": "barbarousbase.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cautiouscherries.com": { - "domain": "cautiouscherries.com", + "basilfish.com": { + "domain": "basilfish.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cautiouscredit.com": { - "domain": "cautiouscredit.com", + "basketballbelieve.com": { + "domain": "basketballbelieve.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cavecurtain.com": { - "domain": "cavecurtain.com", + "baskettexture.com": { + "domain": "baskettexture.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ceciliavenus.com": { - "domain": "ceciliavenus.com", + "bawdybeast.com": { + "domain": "bawdybeast.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "celestialquasar.com": { - "domain": "celestialquasar.com", + "beamvolcano.com": { + "domain": "beamvolcano.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "celestialspectra.com": { - "domain": "celestialspectra.com", + "beancontrol.com": { + "domain": "beancontrol.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "chaireggnog.com": { - "domain": "chaireggnog.com", + "bearmoonlodge.com": { + "domain": "bearmoonlodge.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "chairsdonkey.com": { - "domain": "chairsdonkey.com", + "beetleend.com": { + "domain": "beetleend.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "chalkoil.com": { - "domain": "chalkoil.com", + "begintrain.com": { + "domain": "begintrain.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "changeablecats.com": { - "domain": "changeablecats.com", + "berserkhydrant.com": { + "domain": "berserkhydrant.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "charmingplate.com": { - "domain": "charmingplate.com", + "bespokesandals.com": { + "domain": "bespokesandals.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cheerycraze.com": { - "domain": "cheerycraze.com", + "bestboundary.com": { + "domain": "bestboundary.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "chesscolor.com": { - "domain": "chesscolor.com", + "bewilderedbattle.com": { + "domain": "bewilderedbattle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "childlikeexample.com": { - "domain": "childlikeexample.com", + "bewilderedblade.com": { + "domain": "bewilderedblade.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "chinsnakes.com": { - "domain": "chinsnakes.com", + "bhcumsc.com": { + "domain": "bhcumsc.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "chipperisle.com": { - "domain": "chipperisle.com", + "bikepaws.com": { + "domain": "bikepaws.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "chivalrouscord.com": { - "domain": "chivalrouscord.com", + "bikesboard.com": { + "domain": "bikesboard.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "chunkycactus.com": { - "domain": "chunkycactus.com", + "billowybead.com": { + "domain": "billowybead.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cloisteredcord.com": { - "domain": "cloisteredcord.com", + "binspiredtees.com": { + "domain": "binspiredtees.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cloisteredcurve.com": { - "domain": "cloisteredcurve.com", + "birthdaybelief.com": { + "domain": "birthdaybelief.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "closedcows.com": { - "domain": "closedcows.com", + "blackbrake.com": { + "domain": "blackbrake.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "coatfood.com": { - "domain": "coatfood.com", + "bleachbubble.com": { + "domain": "bleachbubble.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cobaltoverture.com": { - "domain": "cobaltoverture.com", + "bleachscarecrow.com": { + "domain": "bleachscarecrow.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "coldbalance.com": { - "domain": "coldbalance.com", + "bleedlight.com": { + "domain": "bleedlight.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "colossalclouds.com": { - "domain": "colossalclouds.com", + "blesspizzas.com": { + "domain": "blesspizzas.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "colossalcoat.com": { - "domain": "colossalcoat.com", + "blissfulcrescendo.com": { + "domain": "blissfulcrescendo.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "colossalcry.com": { - "domain": "colossalcry.com", + "blissfullagoon.com": { + "domain": "blissfullagoon.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "combbit.com": { - "domain": "combbit.com", + "blueeyedblow.com": { + "domain": "blueeyedblow.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "combcattle.com": { - "domain": "combcattle.com", + "blushingbeast.com": { + "domain": "blushingbeast.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "combcompetition.com": { - "domain": "combcompetition.com", + "boatsvest.com": { + "domain": "boatsvest.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "comfortablecheese.com": { - "domain": "comfortablecheese.com", + "boilingbeetle.com": { + "domain": "boilingbeetle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "concernedchange.com": { - "domain": "concernedchange.com", + "boostbehavior.com": { + "domain": "boostbehavior.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "concernedchickens.com": { - "domain": "concernedchickens.com", + "boredcrown.com": { + "domain": "boredcrown.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "condemnedcomb.com": { - "domain": "condemnedcomb.com", + "bouncyproperty.com": { + "domain": "bouncyproperty.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "conditioncrush.com": { - "domain": "conditioncrush.com", + "boundarybusiness.com": { + "domain": "boundarybusiness.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "confesschairs.com": { - "domain": "confesschairs.com", + "boundlessargument.com": { + "domain": "boundlessargument.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "consciouscheese.com": { - "domain": "consciouscheese.com", + "boundlessbrake.com": { + "domain": "boundlessbrake.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "consciousdirt.com": { - "domain": "consciousdirt.com", + "boundlessveil.com": { + "domain": "boundlessveil.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cooingcoal.com": { - "domain": "cooingcoal.com", + "brainybasin.com": { + "domain": "brainybasin.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "coordinatedcoat.com": { - "domain": "coordinatedcoat.com", + "brainynut.com": { + "domain": "brainynut.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "copycarpenter.com": { - "domain": "copycarpenter.com", + "branchborder.com": { + "domain": "branchborder.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cosmicsculptor.com": { - "domain": "cosmicsculptor.com", + "brandsfive.com": { + "domain": "brandsfive.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "courageousbaby.com": { - "domain": "courageousbaby.com", + "brandybison.com": { + "domain": "brandybison.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "coverapparatus.com": { - "domain": "coverapparatus.com", + "bravebone.com": { + "domain": "bravebone.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cozyhillside.com": { - "domain": "cozyhillside.com", + "bravecalculator.com": { + "domain": "bravecalculator.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cozytryst.com": { - "domain": "cozytryst.com", + "breadbalance.com": { + "domain": "breadbalance.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "creatorcherry.com": { - "domain": "creatorcherry.com", + "breakableinsurance.com": { + "domain": "breakableinsurance.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "creatorpassenger.com": { - "domain": "creatorpassenger.com", + "breakfastboat.com": { + "domain": "breakfastboat.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "creaturecabbage.com": { - "domain": "creaturecabbage.com", + "breezygrove.com": { + "domain": "breezygrove.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "crimsonmeadow.com": { - "domain": "crimsonmeadow.com", + "brianwould.com": { + "domain": "brianwould.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "critictruck.com": { - "domain": "critictruck.com", + "brighttoe.com": { + "domain": "brighttoe.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "crookedcreature.com": { - "domain": "crookedcreature.com", + "briskstorm.com": { + "domain": "briskstorm.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "crystalboulevard.com": { - "domain": "crystalboulevard.com", + "broadborder.com": { + "domain": "broadborder.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cubchannel.com": { - "domain": "cubchannel.com", + "broadboundary.com": { + "domain": "broadboundary.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cuddlylunchroom.com": { - "domain": "cuddlylunchroom.com", + "broadcastbed.com": { + "domain": "broadcastbed.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "currentcollar.com": { - "domain": "currentcollar.com", + "broaddoor.com": { + "domain": "broaddoor.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "curvycry.com": { - "domain": "curvycry.com", + "brotherslocket.com": { + "domain": "brotherslocket.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "cushionpig.com": { - "domain": "cushionpig.com", + "bruisebaseball.com": { + "domain": "bruisebaseball.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "damagedadvice.com": { - "domain": "damagedadvice.com", + "brunchforher.com": { + "domain": "brunchforher.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "damageddistance.com": { - "domain": "damageddistance.com", + "buildingknife.com": { + "domain": "buildingknife.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dandydune.com": { - "domain": "dandydune.com", + "bulbbait.com": { + "domain": "bulbbait.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dandyglow.com": { - "domain": "dandyglow.com", + "burgersalt.com": { + "domain": "burgersalt.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "daughterstone.com": { - "domain": "daughterstone.com", + "burlywhistle.com": { + "domain": "burlywhistle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dazzlingbook.com": { - "domain": "dazzlingbook.com", + "burnbubble.com": { + "domain": "burnbubble.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "debonairdust.com": { - "domain": "debonairdust.com", + "bushesbag.com": { + "domain": "bushesbag.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "debonairtree.com": { - "domain": "debonairtree.com", + "bustlingbath.com": { + "domain": "bustlingbath.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "decisivedrawer.com": { - "domain": "decisivedrawer.com", + "bustlingbook.com": { + "domain": "bustlingbook.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "decisiveducks.com": { - "domain": "decisiveducks.com", + "butterburst.com": { + "domain": "butterburst.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "deerbeginner.com": { - "domain": "deerbeginner.com", + "cakesdrum.com": { + "domain": "cakesdrum.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "defeatedbadge.com": { - "domain": "defeatedbadge.com", + "calculatingcircle.com": { + "domain": "calculatingcircle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "delicatecascade.com": { - "domain": "delicatecascade.com", + "calculatingtoothbrush.com": { + "domain": "calculatingtoothbrush.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "deliciousducks.com": { - "domain": "deliciousducks.com", + "callousbrake.com": { + "domain": "callousbrake.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dependenttrip.com": { - "domain": "dependenttrip.com", + "calmcactus.com": { + "domain": "calmcactus.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "detailedkitten.com": { - "domain": "detailedkitten.com", + "calypsocapsule.com": { + "domain": "calypsocapsule.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dewdroplagoon.com": { - "domain": "dewdroplagoon.com", + "cannonchange.com": { + "domain": "cannonchange.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "digestiondrawer.com": { - "domain": "digestiondrawer.com", + "capablecows.com": { + "domain": "capablecows.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dinnerquartz.com": { - "domain": "dinnerquartz.com", + "capriciouscorn.com": { + "domain": "capriciouscorn.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "diplomahawaii.com": { - "domain": "diplomahawaii.com", + "captivatingcanyon.com": { + "domain": "captivatingcanyon.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "discreetquarter.com": { - "domain": "discreetquarter.com", + "captivatingillusion.com": { + "domain": "captivatingillusion.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dk4ywix.com": { - "domain": "dk4ywix.com", + "captivatingpanorama.com": { + "domain": "captivatingpanorama.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dollardelta.com": { - "domain": "dollardelta.com", + "captivatingperformance.com": { + "domain": "captivatingperformance.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dq95d35.com": { - "domain": "dq95d35.com", + "carefuldolls.com": { + "domain": "carefuldolls.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dreamycanyon.com": { - "domain": "dreamycanyon.com", + "caringcast.com": { + "domain": "caringcast.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "drollwharf.com": { - "domain": "drollwharf.com", + "caringzinc.com": { + "domain": "caringzinc.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dustydime.com": { - "domain": "dustydime.com", + "carloforward.com": { + "domain": "carloforward.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "dustyhammer.com": { - "domain": "dustyhammer.com", + "carscannon.com": { + "domain": "carscannon.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "eagereden.com": { - "domain": "eagereden.com", + "cartkitten.com": { + "domain": "cartkitten.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "eagerknight.com": { - "domain": "eagerknight.com", + "catalogcake.com": { + "domain": "catalogcake.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "echoinghaven.com": { - "domain": "echoinghaven.com", + "catschickens.com": { + "domain": "catschickens.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "effervescentcoral.com": { - "domain": "effervescentcoral.com", + "causecherry.com": { + "domain": "causecherry.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "effervescentvista.com": { - "domain": "effervescentvista.com", + "cautiouscamera.com": { + "domain": "cautiouscamera.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "effulgenttempest.com": { - "domain": "effulgenttempest.com", + "cautiouscherries.com": { + "domain": "cautiouscherries.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "elasticchange.com": { - "domain": "elasticchange.com", + "cautiouscrate.com": { + "domain": "cautiouscrate.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "elderlybean.com": { - "domain": "elderlybean.com", + "cautiouscredit.com": { + "domain": "cautiouscredit.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "elusivebreeze.com": { - "domain": "elusivebreeze.com", + "cavecurtain.com": { + "domain": "cavecurtain.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "eminentbubble.com": { - "domain": "eminentbubble.com", + "ceciliavenus.com": { + "domain": "ceciliavenus.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "enchantingdiscovery.com": { - "domain": "enchantingdiscovery.com", + "celestialeuphony.com": { + "domain": "celestialeuphony.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "enchantingmystique.com": { - "domain": "enchantingmystique.com", + "celestialquasar.com": { + "domain": "celestialquasar.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "endurablebulb.com": { - "domain": "endurablebulb.com", + "celestialspectra.com": { + "domain": "celestialspectra.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "energeticladybug.com": { - "domain": "energeticladybug.com", + "chaireggnog.com": { + "domain": "chaireggnog.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "engineertrick.com": { - "domain": "engineertrick.com", + "chairscrack.com": { + "domain": "chairscrack.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "enigmaticcanyon.com": { - "domain": "enigmaticcanyon.com", + "chairsdonkey.com": { + "domain": "chairsdonkey.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "enigmaticvoyage.com": { - "domain": "enigmaticvoyage.com", + "chalkoil.com": { + "domain": "chalkoil.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "entertainskin.com": { - "domain": "entertainskin.com", + "changeablecats.com": { + "domain": "changeablecats.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "equablekettle.com": { - "domain": "equablekettle.com", + "channelcamp.com": { + "domain": "channelcamp.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ethereallagoon.com": { - "domain": "ethereallagoon.com", + "charmingplate.com": { + "domain": "charmingplate.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "evanescentedge.com": { - "domain": "evanescentedge.com", + "charscroll.com": { + "domain": "charscroll.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "evasivejar.com": { - "domain": "evasivejar.com", + "cheerycraze.com": { + "domain": "cheerycraze.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "eventexistence.com": { - "domain": "eventexistence.com", + "chessbranch.com": { + "domain": "chessbranch.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "exampleshake.com": { - "domain": "exampleshake.com", + "chesscolor.com": { + "domain": "chesscolor.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "excitingtub.com": { - "domain": "excitingtub.com", + "chesscrowd.com": { + "domain": "chesscrowd.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "executeknowledge.com": { - "domain": "executeknowledge.com", + "childlikeexample.com": { + "domain": "childlikeexample.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "exhibitsneeze.com": { - "domain": "exhibitsneeze.com", + "chilledliquid.com": { + "domain": "chilledliquid.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "exquisiteartisanship.com": { - "domain": "exquisiteartisanship.com", + "chingovernment.com": { + "domain": "chingovernment.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "exuberantedge.com": { - "domain": "exuberantedge.com", + "chinsnakes.com": { + "domain": "chinsnakes.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "facilitatebreakfast.com": { - "domain": "facilitatebreakfast.com", + "chipperisle.com": { + "domain": "chipperisle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fadedsnow.com": { - "domain": "fadedsnow.com", + "chivalrouscord.com": { + "domain": "chivalrouscord.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fairiesbranch.com": { - "domain": "fairiesbranch.com", + "chubbycreature.com": { + "domain": "chubbycreature.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fairytaleflame.com": { - "domain": "fairytaleflame.com", + "chunkycactus.com": { + "domain": "chunkycactus.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fancyactivity.com": { - "domain": "fancyactivity.com", + "cicdserver.com": { + "domain": "cicdserver.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fancydune.com": { - "domain": "fancydune.com", + "cinemabonus.com": { + "domain": "cinemabonus.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "farshake.com": { - "domain": "farshake.com", + "clammychicken.com": { + "domain": "clammychicken.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "farsnails.com": { - "domain": "farsnails.com", + "cloisteredcord.com": { + "domain": "cloisteredcord.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fastenfather.com": { - "domain": "fastenfather.com", + "cloisteredcurve.com": { + "domain": "cloisteredcurve.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fatcoil.com": { - "domain": "fatcoil.com", + "closedcows.com": { + "domain": "closedcows.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "faucetfoot.com": { - "domain": "faucetfoot.com", + "closefriction.com": { + "domain": "closefriction.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "faultycanvas.com": { - "domain": "faultycanvas.com", + "cloudhustles.com": { + "domain": "cloudhustles.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fearfulmint.com": { - "domain": "fearfulmint.com", + "cloudjumbo.com": { + "domain": "cloudjumbo.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "featherstage.com": { - "domain": "featherstage.com", + "clovercabbage.com": { + "domain": "clovercabbage.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "feignedfaucet.com": { - "domain": "feignedfaucet.com", + "clumsycar.com": { + "domain": "clumsycar.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fertilefeeling.com": { - "domain": "fertilefeeling.com", + "coatfood.com": { + "domain": "coatfood.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fewjuice.com": { - "domain": "fewjuice.com", + "cobaltoverture.com": { + "domain": "cobaltoverture.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fewkittens.com": { - "domain": "fewkittens.com", + "coffeesidehustle.com": { + "domain": "coffeesidehustle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "firstfrogs.com": { - "domain": "firstfrogs.com", + "coldbalance.com": { + "domain": "coldbalance.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "flameuncle.com": { - "domain": "flameuncle.com", + "coldcreatives.com": { + "domain": "coldcreatives.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "flimsycircle.com": { - "domain": "flimsycircle.com", + "colorfulafterthought.com": { + "domain": "colorfulafterthought.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "flimsythought.com": { - "domain": "flimsythought.com", + "colossalclouds.com": { + "domain": "colossalclouds.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "flourishingcollaboration.com": { - "domain": "flourishingcollaboration.com", + "colossalcoat.com": { + "domain": "colossalcoat.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "flourishinginnovation.com": { - "domain": "flourishinginnovation.com", + "colossalcry.com": { + "domain": "colossalcry.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "flourishingpartnership.com": { - "domain": "flourishingpartnership.com", + "combativedetail.com": { + "domain": "combativedetail.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "flowerycreature.com": { - "domain": "flowerycreature.com", + "combbit.com": { + "domain": "combbit.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "floweryfact.com": { - "domain": "floweryfact.com", + "combcattle.com": { + "domain": "combcattle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "followborder.com": { - "domain": "followborder.com", + "combcompetition.com": { + "domain": "combcompetition.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "forgetfulsnail.com": { - "domain": "forgetfulsnail.com", + "cometquote.com": { + "domain": "cometquote.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "franticroof.com": { - "domain": "franticroof.com", + "comfortablecheese.com": { + "domain": "comfortablecheese.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "frequentflesh.com": { - "domain": "frequentflesh.com", + "comfygoodness.com": { + "domain": "comfygoodness.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "friendlycrayon.com": { - "domain": "friendlycrayon.com", + "companyparcel.com": { + "domain": "companyparcel.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "friendwool.com": { - "domain": "friendwool.com", + "comparereaction.com": { + "domain": "comparereaction.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fumblingform.com": { - "domain": "fumblingform.com", + "compiledoctor.com": { + "domain": "compiledoctor.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "furryfork.com": { - "domain": "furryfork.com", + "concernedchange.com": { + "domain": "concernedchange.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "futuristicfifth.com": { - "domain": "futuristicfifth.com", + "concernedchickens.com": { + "domain": "concernedchickens.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "futuristicframe.com": { - "domain": "futuristicframe.com", + "condemnedcomb.com": { + "domain": "condemnedcomb.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "fuzzyerror.com": { - "domain": "fuzzyerror.com", + "conditionchange.com": { + "domain": "conditionchange.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "gaudyairplane.com": { - "domain": "gaudyairplane.com", + "conditioncrush.com": { + "domain": "conditioncrush.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "generateoffice.com": { - "domain": "generateoffice.com", + "confesschairs.com": { + "domain": "confesschairs.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "giantsvessel.com": { - "domain": "giantsvessel.com", + "configchain.com": { + "domain": "configchain.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "giddycoat.com": { - "domain": "giddycoat.com", + "connectashelf.com": { + "domain": "connectashelf.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "givevacation.com": { - "domain": "givevacation.com", + "consciouschairs.com": { + "domain": "consciouschairs.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "gladysway.com": { - "domain": "gladysway.com", + "consciouscheese.com": { + "domain": "consciouscheese.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "gleamingcow.com": { - "domain": "gleamingcow.com", + "consciousdirt.com": { + "domain": "consciousdirt.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "glisteningguide.com": { - "domain": "glisteningguide.com", + "consumerzero.com": { + "domain": "consumerzero.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "glitteringbrook.com": { - "domain": "glitteringbrook.com", + "controlcola.com": { + "domain": "controlcola.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "goldfishgrowth.com": { - "domain": "goldfishgrowth.com", + "controlhall.com": { + "domain": "controlhall.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "gondolagnome.com": { - "domain": "gondolagnome.com", + "convertbatch.com": { + "domain": "convertbatch.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "gracefulmilk.com": { - "domain": "gracefulmilk.com", + "cooingcoal.com": { + "domain": "cooingcoal.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "grandfatherguitar.com": { - "domain": "grandfatherguitar.com", + "coordinatedbedroom.com": { + "domain": "coordinatedbedroom.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "grayoranges.com": { - "domain": "grayoranges.com", + "coordinatedcoat.com": { + "domain": "coordinatedcoat.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "grayreceipt.com": { - "domain": "grayreceipt.com", + "copycarpenter.com": { + "domain": "copycarpenter.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "grouchypush.com": { - "domain": "grouchypush.com", + "copyrightaccesscontrols.com": { + "domain": "copyrightaccesscontrols.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "grumpydime.com": { - "domain": "grumpydime.com", + "coralreverie.com": { + "domain": "coralreverie.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "guardeddirection.com": { - "domain": "guardeddirection.com", + "corgibeachday.com": { + "domain": "corgibeachday.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "guidecent.com": { - "domain": "guidecent.com", + "cosmicsculptor.com": { + "domain": "cosmicsculptor.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "gulliblegrip.com": { - "domain": "gulliblegrip.com", + "cosmosjackson.com": { + "domain": "cosmosjackson.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "gustygrandmother.com": { - "domain": "gustygrandmother.com", + "courageousbaby.com": { + "domain": "courageousbaby.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "halcyoncanyon.com": { - "domain": "halcyoncanyon.com", + "coverapparatus.com": { + "domain": "coverapparatus.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "halcyonsculpture.com": { - "domain": "halcyonsculpture.com", + "coverlayer.com": { + "domain": "coverlayer.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "hallowedinvention.com": { - "domain": "hallowedinvention.com", + "cozydusk.com": { + "domain": "cozydusk.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "haltingdivision.com": { - "domain": "haltingdivision.com", + "cozyhillside.com": { + "domain": "cozyhillside.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "haltinggold.com": { - "domain": "haltinggold.com", + "cozytryst.com": { + "domain": "cozytryst.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "handsomehose.com": { - "domain": "handsomehose.com", + "crackedsafe.com": { + "domain": "crackedsafe.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "crafthenry.com": { + "domain": "crafthenry.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "crashchance.com": { + "domain": "crashchance.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "craterbox.com": { + "domain": "craterbox.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "creatorcherry.com": { + "domain": "creatorcherry.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "creatorpassenger.com": { + "domain": "creatorpassenger.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "creaturecabbage.com": { + "domain": "creaturecabbage.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "crimsonmeadow.com": { + "domain": "crimsonmeadow.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "critictruck.com": { + "domain": "critictruck.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "crookedcreature.com": { + "domain": "crookedcreature.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "cruisetourist.com": { + "domain": "cruisetourist.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "cryptvalue.com": { + "domain": "cryptvalue.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "crystalboulevard.com": { + "domain": "crystalboulevard.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "crystalstatus.com": { + "domain": "crystalstatus.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "cubchannel.com": { + "domain": "cubchannel.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "cubepins.com": { + "domain": "cubepins.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "cuddlycake.com": { + "domain": "cuddlycake.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "cuddlylunchroom.com": { + "domain": "cuddlylunchroom.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "culturedcamera.com": { + "domain": "culturedcamera.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "culturedfeather.com": { + "domain": "culturedfeather.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "cumbersomecar.com": { + "domain": "cumbersomecar.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "cumbersomecloud.com": { + "domain": "cumbersomecloud.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "curiouschalk.com": { + "domain": "curiouschalk.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "curioussuccess.com": { + "domain": "curioussuccess.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "curlycannon.com": { + "domain": "curlycannon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "currentcollar.com": { + "domain": "currentcollar.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "curtaincows.com": { + "domain": "curtaincows.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "curvycord.com": { + "domain": "curvycord.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "curvycry.com": { + "domain": "curvycry.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "cushionpig.com": { + "domain": "cushionpig.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "cutcurrent.com": { + "domain": "cutcurrent.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "cyclopsdial.com": { + "domain": "cyclopsdial.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dailydivision.com": { + "domain": "dailydivision.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "damagedadvice.com": { + "domain": "damagedadvice.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "damageddistance.com": { + "domain": "damageddistance.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dancemistake.com": { + "domain": "dancemistake.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dandydune.com": { + "domain": "dandydune.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dandyglow.com": { + "domain": "dandyglow.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dapperdiscussion.com": { + "domain": "dapperdiscussion.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "datastoried.com": { + "domain": "datastoried.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "daughterstone.com": { + "domain": "daughterstone.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "daymodern.com": { + "domain": "daymodern.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dazzlingbook.com": { + "domain": "dazzlingbook.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "deafeningdock.com": { + "domain": "deafeningdock.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "deafeningdowntown.com": { + "domain": "deafeningdowntown.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "debonairdust.com": { + "domain": "debonairdust.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "debonairtree.com": { + "domain": "debonairtree.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "debugentity.com": { + "domain": "debugentity.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "decidedrum.com": { + "domain": "decidedrum.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "decisivedrawer.com": { + "domain": "decisivedrawer.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "decisiveducks.com": { + "domain": "decisiveducks.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "decoycreation.com": { + "domain": "decoycreation.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "deerbeginner.com": { + "domain": "deerbeginner.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "defeatedbadge.com": { + "domain": "defeatedbadge.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "defensevest.com": { + "domain": "defensevest.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "degreechariot.com": { + "domain": "degreechariot.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "delegatediscussion.com": { + "domain": "delegatediscussion.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "delicatecascade.com": { + "domain": "delicatecascade.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "deliciousducks.com": { + "domain": "deliciousducks.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "deltafault.com": { + "domain": "deltafault.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "deluxecrate.com": { + "domain": "deluxecrate.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dependenttrip.com": { + "domain": "dependenttrip.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "desirebucket.com": { + "domain": "desirebucket.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "desiredirt.com": { + "domain": "desiredirt.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "detailedgovernment.com": { + "domain": "detailedgovernment.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "detailedkitten.com": { + "domain": "detailedkitten.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "detectdinner.com": { + "domain": "detectdinner.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "detourgame.com": { + "domain": "detourgame.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "deviceseal.com": { + "domain": "deviceseal.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "deviceworkshop.com": { + "domain": "deviceworkshop.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dewdroplagoon.com": { + "domain": "dewdroplagoon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "difficultfog.com": { + "domain": "difficultfog.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "digestiondrawer.com": { + "domain": "digestiondrawer.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dinnerquartz.com": { + "domain": "dinnerquartz.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "diplomahawaii.com": { + "domain": "diplomahawaii.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "direfuldesk.com": { + "domain": "direfuldesk.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "discreetquarter.com": { + "domain": "discreetquarter.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "distributionneck.com": { + "domain": "distributionneck.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "distributionpocket.com": { + "domain": "distributionpocket.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "distributiontomatoes.com": { + "domain": "distributiontomatoes.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "disturbedquiet.com": { + "domain": "disturbedquiet.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "divehope.com": { + "domain": "divehope.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dk4ywix.com": { + "domain": "dk4ywix.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dogsonclouds.com": { + "domain": "dogsonclouds.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dollardelta.com": { + "domain": "dollardelta.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "doubledefend.com": { + "domain": "doubledefend.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "doubtdrawer.com": { + "domain": "doubtdrawer.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dq95d35.com": { + "domain": "dq95d35.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dreamycanyon.com": { + "domain": "dreamycanyon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "driftpizza.com": { + "domain": "driftpizza.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "drollwharf.com": { + "domain": "drollwharf.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "drydrum.com": { + "domain": "drydrum.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dustydime.com": { + "domain": "dustydime.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "dustyhammer.com": { + "domain": "dustyhammer.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "eagereden.com": { + "domain": "eagereden.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "eagerflame.com": { + "domain": "eagerflame.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "eagerknight.com": { + "domain": "eagerknight.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "earthyfarm.com": { + "domain": "earthyfarm.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "eatablesquare.com": { + "domain": "eatablesquare.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "echochief.com": { + "domain": "echochief.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "echoinghaven.com": { + "domain": "echoinghaven.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "effervescentcoral.com": { + "domain": "effervescentcoral.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "effervescentvista.com": { + "domain": "effervescentvista.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "effulgentnook.com": { + "domain": "effulgentnook.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "effulgenttempest.com": { + "domain": "effulgenttempest.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "ejyymghi.com": { + "domain": "ejyymghi.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "elasticchange.com": { + "domain": "elasticchange.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "elderlybean.com": { + "domain": "elderlybean.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "elderlytown.com": { + "domain": "elderlytown.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "elephantqueue.com": { + "domain": "elephantqueue.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "elusivebreeze.com": { + "domain": "elusivebreeze.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "elusivecascade.com": { + "domain": "elusivecascade.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "elysiantraverse.com": { + "domain": "elysiantraverse.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "embellishedmeadow.com": { + "domain": "embellishedmeadow.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "embermosaic.com": { + "domain": "embermosaic.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "emberwhisper.com": { + "domain": "emberwhisper.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "eminentbubble.com": { + "domain": "eminentbubble.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "eminentend.com": { + "domain": "eminentend.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "emptyescort.com": { + "domain": "emptyescort.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enchantedskyline.com": { + "domain": "enchantedskyline.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enchantingdiscovery.com": { + "domain": "enchantingdiscovery.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enchantingenchantment.com": { + "domain": "enchantingenchantment.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enchantingmystique.com": { + "domain": "enchantingmystique.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enchantingtundra.com": { + "domain": "enchantingtundra.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enchantingvalley.com": { + "domain": "enchantingvalley.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "encourageshock.com": { + "domain": "encourageshock.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "endlesstrust.com": { + "domain": "endlesstrust.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "endurablebulb.com": { + "domain": "endurablebulb.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "energeticexample.com": { + "domain": "energeticexample.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "energeticladybug.com": { + "domain": "energeticladybug.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "engineergrape.com": { + "domain": "engineergrape.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "engineertrick.com": { + "domain": "engineertrick.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enigmaticblossom.com": { + "domain": "enigmaticblossom.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enigmaticcanyon.com": { + "domain": "enigmaticcanyon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enigmaticvoyage.com": { + "domain": "enigmaticvoyage.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enormousfoot.com": { + "domain": "enormousfoot.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enterdrama.com": { + "domain": "enterdrama.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "entertainskin.com": { + "domain": "entertainskin.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enthusiastictemper.com": { + "domain": "enthusiastictemper.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "enviousthread.com": { + "domain": "enviousthread.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "equablekettle.com": { + "domain": "equablekettle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "etherealbamboo.com": { + "domain": "etherealbamboo.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "ethereallagoon.com": { + "domain": "ethereallagoon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "etherealpinnacle.com": { + "domain": "etherealpinnacle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "etherealquasar.com": { + "domain": "etherealquasar.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "etherealripple.com": { + "domain": "etherealripple.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "evanescentedge.com": { + "domain": "evanescentedge.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "evasivejar.com": { + "domain": "evasivejar.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "eventexistence.com": { + "domain": "eventexistence.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "exampleshake.com": { + "domain": "exampleshake.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "excitingtub.com": { + "domain": "excitingtub.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "exclusivebrass.com": { + "domain": "exclusivebrass.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "executeknowledge.com": { + "domain": "executeknowledge.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "exhibitsneeze.com": { + "domain": "exhibitsneeze.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "exquisiteartisanship.com": { + "domain": "exquisiteartisanship.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "extractobservation.com": { + "domain": "extractobservation.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "extralocker.com": { + "domain": "extralocker.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "extramonies.com": { + "domain": "extramonies.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "exuberantedge.com": { + "domain": "exuberantedge.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "facilitatebreakfast.com": { + "domain": "facilitatebreakfast.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fadechildren.com": { + "domain": "fadechildren.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fadedsnow.com": { + "domain": "fadedsnow.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fairfeeling.com": { + "domain": "fairfeeling.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fairiesbranch.com": { + "domain": "fairiesbranch.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fairytaleflame.com": { + "domain": "fairytaleflame.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "falseframe.com": { + "domain": "falseframe.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "familiarrod.com": { + "domain": "familiarrod.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fancyactivity.com": { + "domain": "fancyactivity.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fancydune.com": { + "domain": "fancydune.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fancygrove.com": { + "domain": "fancygrove.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fangfeeling.com": { + "domain": "fangfeeling.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fantastictone.com": { + "domain": "fantastictone.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "farethief.com": { + "domain": "farethief.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "farshake.com": { + "domain": "farshake.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "farsnails.com": { + "domain": "farsnails.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fastenfather.com": { + "domain": "fastenfather.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fasterfineart.com": { + "domain": "fasterfineart.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fasterjson.com": { + "domain": "fasterjson.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fatcoil.com": { + "domain": "fatcoil.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "faucetfoot.com": { + "domain": "faucetfoot.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "faultycanvas.com": { + "domain": "faultycanvas.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fearfulfish.com": { + "domain": "fearfulfish.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fearfulmint.com": { + "domain": "fearfulmint.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fearlesstramp.com": { + "domain": "fearlesstramp.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "featherstage.com": { + "domain": "featherstage.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "feeblestamp.com": { + "domain": "feeblestamp.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "feignedfaucet.com": { + "domain": "feignedfaucet.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fernwaycloud.com": { + "domain": "fernwaycloud.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fertilefeeling.com": { + "domain": "fertilefeeling.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fewjuice.com": { + "domain": "fewjuice.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fewkittens.com": { + "domain": "fewkittens.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "finalizeforce.com": { + "domain": "finalizeforce.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "finestpiece.com": { + "domain": "finestpiece.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "finitecube.com": { + "domain": "finitecube.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "firecatfilms.com": { + "domain": "firecatfilms.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fireworkcamp.com": { + "domain": "fireworkcamp.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "firstendpoint.com": { + "domain": "firstendpoint.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "firstfrogs.com": { + "domain": "firstfrogs.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "firsttexture.com": { + "domain": "firsttexture.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fitmessage.com": { + "domain": "fitmessage.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fivesidedsquare.com": { + "domain": "fivesidedsquare.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "flakyfeast.com": { + "domain": "flakyfeast.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "flameuncle.com": { + "domain": "flameuncle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "flimsycircle.com": { + "domain": "flimsycircle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "flimsythought.com": { + "domain": "flimsythought.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "flippedfunnel.com": { + "domain": "flippedfunnel.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "floodprincipal.com": { + "domain": "floodprincipal.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "flourishingcollaboration.com": { + "domain": "flourishingcollaboration.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "flourishingendeavor.com": { + "domain": "flourishingendeavor.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "flourishinginnovation.com": { + "domain": "flourishinginnovation.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "flourishingpartnership.com": { + "domain": "flourishingpartnership.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "flowersornament.com": { + "domain": "flowersornament.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "flowerycreature.com": { + "domain": "flowerycreature.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "floweryfact.com": { + "domain": "floweryfact.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "floweryoperation.com": { + "domain": "floweryoperation.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "foambench.com": { + "domain": "foambench.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "followborder.com": { + "domain": "followborder.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "forecasttiger.com": { + "domain": "forecasttiger.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "foretellfifth.com": { + "domain": "foretellfifth.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "forevergears.com": { + "domain": "forevergears.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "forgetfulflowers.com": { + "domain": "forgetfulflowers.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "forgetfulsnail.com": { + "domain": "forgetfulsnail.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fractalcoast.com": { + "domain": "fractalcoast.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "framebanana.com": { + "domain": "framebanana.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "franticroof.com": { + "domain": "franticroof.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "frantictrail.com": { + "domain": "frantictrail.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "frazzleart.com": { + "domain": "frazzleart.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "freakyglass.com": { + "domain": "freakyglass.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "frequentflesh.com": { + "domain": "frequentflesh.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "friendlycrayon.com": { + "domain": "friendlycrayon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "friendlyfold.com": { + "domain": "friendlyfold.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "friendwool.com": { + "domain": "friendwool.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "frightenedpotato.com": { + "domain": "frightenedpotato.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "frogator.com": { + "domain": "frogator.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "frogtray.com": { + "domain": "frogtray.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "frugalfiestas.com": { + "domain": "frugalfiestas.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fumblingform.com": { + "domain": "fumblingform.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "functionalcrown.com": { + "domain": "functionalcrown.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "funoverbored.com": { + "domain": "funoverbored.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "funoverflow.com": { + "domain": "funoverflow.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "furnstudio.com": { + "domain": "furnstudio.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "furryfork.com": { + "domain": "furryfork.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "furryhorses.com": { + "domain": "furryhorses.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "futuristicapparatus.com": { + "domain": "futuristicapparatus.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "futuristicfairies.com": { + "domain": "futuristicfairies.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "futuristicfifth.com": { + "domain": "futuristicfifth.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "futuristicframe.com": { + "domain": "futuristicframe.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fuzzyaudio.com": { + "domain": "fuzzyaudio.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fuzzyerror.com": { + "domain": "fuzzyerror.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "fvl1f.pw": { + "domain": "fvl1f.pw", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gardenovens.com": { + "domain": "gardenovens.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gaudyairplane.com": { + "domain": "gaudyairplane.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "geekactive.com": { + "domain": "geekactive.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "generalprose.com": { + "domain": "generalprose.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "generateoffice.com": { + "domain": "generateoffice.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "giantsvessel.com": { + "domain": "giantsvessel.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "giddycoat.com": { + "domain": "giddycoat.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gitcrumbs.com": { + "domain": "gitcrumbs.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "givevacation.com": { + "domain": "givevacation.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gladglen.com": { + "domain": "gladglen.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gladysway.com": { + "domain": "gladysway.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "glamhawk.com": { + "domain": "glamhawk.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gleamingcow.com": { + "domain": "gleamingcow.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gleaminghaven.com": { + "domain": "gleaminghaven.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "glisteningguide.com": { + "domain": "glisteningguide.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "glisteningsign.com": { + "domain": "glisteningsign.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "glitteringbrook.com": { + "domain": "glitteringbrook.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "glowingmeadow.com": { + "domain": "glowingmeadow.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gluedpixel.com": { + "domain": "gluedpixel.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "goldfishgrowth.com": { + "domain": "goldfishgrowth.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gondolagnome.com": { + "domain": "gondolagnome.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "goodbark.com": { + "domain": "goodbark.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gracefulmilk.com": { + "domain": "gracefulmilk.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "grandfatherguitar.com": { + "domain": "grandfatherguitar.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gravitygive.com": { + "domain": "gravitygive.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gravitykick.com": { + "domain": "gravitykick.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "grayoranges.com": { + "domain": "grayoranges.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "grayreceipt.com": { + "domain": "grayreceipt.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "greyinstrument.com": { + "domain": "greyinstrument.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gripcorn.com": { + "domain": "gripcorn.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "groovyornament.com": { + "domain": "groovyornament.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "grouchybrothers.com": { + "domain": "grouchybrothers.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "grouchypush.com": { + "domain": "grouchypush.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "grumpydime.com": { + "domain": "grumpydime.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "grumpydrawer.com": { + "domain": "grumpydrawer.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "guardeddirection.com": { + "domain": "guardeddirection.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "guardedschool.com": { + "domain": "guardedschool.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "guessdetail.com": { + "domain": "guessdetail.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "guidecent.com": { + "domain": "guidecent.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "guildalpha.com": { + "domain": "guildalpha.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gulliblegrip.com": { + "domain": "gulliblegrip.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gustocooking.com": { + "domain": "gustocooking.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "gustygrandmother.com": { + "domain": "gustygrandmother.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "h78xb.pw": { + "domain": "h78xb.pw", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "habitualhumor.com": { + "domain": "habitualhumor.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "halcyoncanyon.com": { + "domain": "halcyoncanyon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "halcyonsculpture.com": { + "domain": "halcyonsculpture.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hallowedinvention.com": { + "domain": "hallowedinvention.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "haltingdivision.com": { + "domain": "haltingdivision.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "haltinggold.com": { + "domain": "haltinggold.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "handleteeth.com": { + "domain": "handleteeth.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "handnorth.com": { + "domain": "handnorth.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "handsomehose.com": { + "domain": "handsomehose.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "handsomeindustry.com": { + "domain": "handsomeindustry.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "handsomelythumb.com": { + "domain": "handsomelythumb.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "handsomeyam.com": { + "domain": "handsomeyam.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "handyfield.com": { + "domain": "handyfield.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "handyfireman.com": { + "domain": "handyfireman.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "handyincrease.com": { + "domain": "handyincrease.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "haplesshydrant.com": { + "domain": "haplesshydrant.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "haplessland.com": { + "domain": "haplessland.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "happysponge.com": { + "domain": "happysponge.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "harborcub.com": { + "domain": "harborcub.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "harmonicbamboo.com": { + "domain": "harmonicbamboo.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "harmonywing.com": { + "domain": "harmonywing.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hatefulrequest.com": { + "domain": "hatefulrequest.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "headydegree.com": { + "domain": "headydegree.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "headyhook.com": { + "domain": "headyhook.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "healflowers.com": { + "domain": "healflowers.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hearinglizards.com": { + "domain": "hearinglizards.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "heartbreakingmind.com": { + "domain": "heartbreakingmind.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hearthorn.com": { + "domain": "hearthorn.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "heavydetail.com": { + "domain": "heavydetail.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "heavyplayground.com": { + "domain": "heavyplayground.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "helpcollar.com": { + "domain": "helpcollar.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "helpflame.com": { + "domain": "helpflame.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hfc195b.com": { + "domain": "hfc195b.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "highfalutinbox.com": { + "domain": "highfalutinbox.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "highfalutinhoney.com": { + "domain": "highfalutinhoney.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hilariouszinc.com": { + "domain": "hilariouszinc.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "historicalbeam.com": { + "domain": "historicalbeam.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "homelycrown.com": { + "domain": "homelycrown.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "honeybulb.com": { + "domain": "honeybulb.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "honeywhipped.com": { + "domain": "honeywhipped.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "honorablehydrant.com": { + "domain": "honorablehydrant.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "horsenectar.com": { + "domain": "horsenectar.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hospitablehall.com": { + "domain": "hospitablehall.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hospitablehat.com": { + "domain": "hospitablehat.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "howdyinbox.com": { + "domain": "howdyinbox.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "humdrumhobbies.com": { + "domain": "humdrumhobbies.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "humdrumtouch.com": { + "domain": "humdrumtouch.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hurtgrape.com": { + "domain": "hurtgrape.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hypnoticwound.com": { + "domain": "hypnoticwound.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hystericalcloth.com": { + "domain": "hystericalcloth.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "hystericalfinger.com": { + "domain": "hystericalfinger.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "i9w8p.pw": { + "domain": "i9w8p.pw", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "idolscene.com": { + "domain": "idolscene.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "idyllicjazz.com": { + "domain": "idyllicjazz.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "illinvention.com": { + "domain": "illinvention.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "illustriousoatmeal.com": { + "domain": "illustriousoatmeal.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "immensehoney.com": { + "domain": "immensehoney.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "imminentshake.com": { + "domain": "imminentshake.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "importantmeat.com": { + "domain": "importantmeat.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "importedincrease.com": { + "domain": "importedincrease.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "importedinsect.com": { + "domain": "importedinsect.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "importlocate.com": { + "domain": "importlocate.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "impossibleexpansion.com": { + "domain": "impossibleexpansion.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "impossiblemove.com": { + "domain": "impossiblemove.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "impulsejewel.com": { + "domain": "impulsejewel.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "impulselumber.com": { + "domain": "impulselumber.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "incomehippo.com": { + "domain": "incomehippo.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "incompetentjoke.com": { + "domain": "incompetentjoke.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "inconclusiveaction.com": { + "domain": "inconclusiveaction.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "infamousstream.com": { + "domain": "infamousstream.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "innocentlamp.com": { + "domain": "innocentlamp.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "innocentwax.com": { + "domain": "innocentwax.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "inputicicle.com": { + "domain": "inputicicle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "inquisitiveice.com": { + "domain": "inquisitiveice.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "inquisitiveinvention.com": { + "domain": "inquisitiveinvention.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "intelligentscissors.com": { + "domain": "intelligentscissors.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "intentlens.com": { + "domain": "intentlens.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "interestdust.com": { + "domain": "interestdust.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "internalcondition.com": { + "domain": "internalcondition.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "internalsink.com": { + "domain": "internalsink.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "iotapool.com": { + "domain": "iotapool.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "irritatingfog.com": { + "domain": "irritatingfog.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "itemslice.com": { + "domain": "itemslice.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "ivykiosk.com": { + "domain": "ivykiosk.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "jadeitite.com": { + "domain": "jadeitite.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "jaderooster.com": { + "domain": "jaderooster.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "jailbulb.com": { + "domain": "jailbulb.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "joblessdrum.com": { + "domain": "joblessdrum.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "jollylens.com": { + "domain": "jollylens.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "joyfulkeen.com": { + "domain": "joyfulkeen.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "joyoussurprise.com": { + "domain": "joyoussurprise.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "jubilantaura.com": { + "domain": "jubilantaura.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "jubilantcanyon.com": { + "domain": "jubilantcanyon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "jubilantcascade.com": { + "domain": "jubilantcascade.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "jubilantglimmer.com": { + "domain": "jubilantglimmer.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "jubilanttempest.com": { + "domain": "jubilanttempest.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "jubilantwhisper.com": { + "domain": "jubilantwhisper.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "justicejudo.com": { + "domain": "justicejudo.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "k54nw.pw": { + "domain": "k54nw.pw", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "kaputquill.com": { + "domain": "kaputquill.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "keenquill.com": { + "domain": "keenquill.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "kindhush.com": { + "domain": "kindhush.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "kitesquirrel.com": { + "domain": "kitesquirrel.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "knitstamp.com": { + "domain": "knitstamp.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "laboredlight.com": { + "domain": "laboredlight.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lameletters.com": { + "domain": "lameletters.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lamplow.com": { + "domain": "lamplow.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "largebrass.com": { + "domain": "largebrass.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lasttaco.com": { + "domain": "lasttaco.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "leaplunchroom.com": { + "domain": "leaplunchroom.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "leftliquid.com": { + "domain": "leftliquid.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lemonpackage.com": { + "domain": "lemonpackage.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lemonsandjoy.com": { + "domain": "lemonsandjoy.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "liftedknowledge.com": { + "domain": "liftedknowledge.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lightenafterthought.com": { + "domain": "lightenafterthought.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lighttalon.com": { + "domain": "lighttalon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "livelumber.com": { + "domain": "livelumber.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "livelylaugh.com": { + "domain": "livelylaugh.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "livelyreward.com": { + "domain": "livelyreward.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "livingsleet.com": { + "domain": "livingsleet.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lizardslaugh.com": { + "domain": "lizardslaugh.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "loadsurprise.com": { + "domain": "loadsurprise.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lonelyflavor.com": { + "domain": "lonelyflavor.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "longingtrees.com": { + "domain": "longingtrees.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lorenzourban.com": { + "domain": "lorenzourban.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "losslace.com": { + "domain": "losslace.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "loudlunch.com": { + "domain": "loudlunch.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "loveseashore.com": { + "domain": "loveseashore.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lp3tdqle.com": { + "domain": "lp3tdqle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "ludicrousarch.com": { + "domain": "ludicrousarch.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lumberamount.com": { + "domain": "lumberamount.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "luminousboulevard.com": { + "domain": "luminousboulevard.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "luminouscatalyst.com": { + "domain": "luminouscatalyst.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "luminoussculptor.com": { + "domain": "luminoussculptor.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lumpygnome.com": { + "domain": "lumpygnome.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lumpylumber.com": { + "domain": "lumpylumber.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lustroushaven.com": { + "domain": "lustroushaven.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "lyricshook.com": { + "domain": "lyricshook.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "madebyintent.com": { + "domain": "madebyintent.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "magicaljoin.com": { + "domain": "magicaljoin.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "magnetairport.com": { + "domain": "magnetairport.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "majesticmountainrange.com": { + "domain": "majesticmountainrange.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "majesticwaterscape.com": { + "domain": "majesticwaterscape.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "majesticwilderness.com": { + "domain": "majesticwilderness.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "maliciousmusic.com": { + "domain": "maliciousmusic.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "managedpush.com": { + "domain": "managedpush.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mantrafox.com": { + "domain": "mantrafox.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "marblediscussion.com": { + "domain": "marblediscussion.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "markahouse.com": { + "domain": "markahouse.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "markedmeasure.com": { + "domain": "markedmeasure.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "marketspiders.com": { + "domain": "marketspiders.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "marriedmailbox.com": { + "domain": "marriedmailbox.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "marriedvalue.com": { + "domain": "marriedvalue.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "massivemark.com": { + "domain": "massivemark.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "materialisticmoon.com": { + "domain": "materialisticmoon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "materialmilk.com": { + "domain": "materialmilk.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "materialplayground.com": { + "domain": "materialplayground.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "meadowlullaby.com": { + "domain": "meadowlullaby.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "meatydime.com": { + "domain": "meatydime.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mediatescarf.com": { + "domain": "mediatescarf.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mediumshort.com": { + "domain": "mediumshort.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mellowhush.com": { + "domain": "mellowhush.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mellowmailbox.com": { + "domain": "mellowmailbox.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "melodiouschorus.com": { + "domain": "melodiouschorus.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "melodiouscomposition.com": { + "domain": "melodiouscomposition.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "meltmilk.com": { + "domain": "meltmilk.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "memopilot.com": { + "domain": "memopilot.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "memorizeneck.com": { + "domain": "memorizeneck.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "meremark.com": { + "domain": "meremark.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "merequartz.com": { + "domain": "merequartz.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "merryopal.com": { + "domain": "merryopal.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "merryvault.com": { + "domain": "merryvault.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "messagenovice.com": { + "domain": "messagenovice.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "messyoranges.com": { + "domain": "messyoranges.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mightyspiders.com": { + "domain": "mightyspiders.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mimosamajor.com": { + "domain": "mimosamajor.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mindfulgem.com": { + "domain": "mindfulgem.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "minorcattle.com": { + "domain": "minorcattle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "minusmental.com": { + "domain": "minusmental.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "minuteburst.com": { + "domain": "minuteburst.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "miscreantmoon.com": { + "domain": "miscreantmoon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mistyhorizon.com": { + "domain": "mistyhorizon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mittencattle.com": { + "domain": "mittencattle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mixedreading.com": { + "domain": "mixedreading.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "modularmental.com": { + "domain": "modularmental.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "monacobeatles.com": { + "domain": "monacobeatles.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "moorshoes.com": { + "domain": "moorshoes.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "motionlessbag.com": { + "domain": "motionlessbag.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "motionlessbelief.com": { + "domain": "motionlessbelief.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "motionlessmeeting.com": { + "domain": "motionlessmeeting.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "movemeal.com": { + "domain": "movemeal.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "muddledaftermath.com": { + "domain": "muddledaftermath.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "muddledmemory.com": { + "domain": "muddledmemory.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mundanenail.com": { + "domain": "mundanenail.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mundanepollution.com": { + "domain": "mundanepollution.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mushywaste.com": { + "domain": "mushywaste.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "muteknife.com": { + "domain": "muteknife.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mutemailbox.com": { + "domain": "mutemailbox.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "mysticalagoon.com": { + "domain": "mysticalagoon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "naivestatement.com": { + "domain": "naivestatement.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nappyneck.com": { + "domain": "nappyneck.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "neatshade.com": { + "domain": "neatshade.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nebulacrescent.com": { + "domain": "nebulacrescent.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nebulajubilee.com": { + "domain": "nebulajubilee.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nebulousamusement.com": { + "domain": "nebulousamusement.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nebulousgarden.com": { + "domain": "nebulousgarden.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nebulousquasar.com": { + "domain": "nebulousquasar.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nebulousripple.com": { + "domain": "nebulousripple.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "needlessnorth.com": { + "domain": "needlessnorth.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "needyneedle.com": { + "domain": "needyneedle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "neighborlywatch.com": { + "domain": "neighborlywatch.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "niftygraphs.com": { + "domain": "niftygraphs.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "niftyhospital.com": { + "domain": "niftyhospital.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "niftyjelly.com": { + "domain": "niftyjelly.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nightwound.com": { + "domain": "nightwound.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nimbleplot.com": { + "domain": "nimbleplot.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nocturnalloom.com": { + "domain": "nocturnalloom.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nocturnalmystique.com": { + "domain": "nocturnalmystique.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "noiselessplough.com": { + "domain": "noiselessplough.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nonchalantnerve.com": { + "domain": "nonchalantnerve.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nondescriptcrowd.com": { + "domain": "nondescriptcrowd.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nondescriptstocking.com": { + "domain": "nondescriptstocking.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nostalgicknot.com": { + "domain": "nostalgicknot.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nostalgicneed.com": { + "domain": "nostalgicneed.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "notifyglass.com": { + "domain": "notifyglass.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nudgeduck.com": { + "domain": "nudgeduck.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nullnorth.com": { + "domain": "nullnorth.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "numberlessring.com": { + "domain": "numberlessring.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "numerousnest.com": { + "domain": "numerousnest.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "nuttyorganization.com": { + "domain": "nuttyorganization.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "oafishchance.com": { + "domain": "oafishchance.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "oafishobservation.com": { + "domain": "oafishobservation.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "obscenesidewalk.com": { + "domain": "obscenesidewalk.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "observantice.com": { + "domain": "observantice.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "oldfashionedoffer.com": { + "domain": "oldfashionedoffer.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "omgthink.com": { + "domain": "omgthink.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "omniscientfeeling.com": { + "domain": "omniscientfeeling.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "onlywoofs.com": { + "domain": "onlywoofs.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "opalquill.com": { + "domain": "opalquill.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "operationchicken.com": { + "domain": "operationchicken.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "operationnail.com": { + "domain": "operationnail.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "oppositeoperation.com": { + "domain": "oppositeoperation.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "optimallimit.com": { + "domain": "optimallimit.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "opulentsylvan.com": { + "domain": "opulentsylvan.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "orientedargument.com": { + "domain": "orientedargument.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "orionember.com": { + "domain": "orionember.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "ourblogthing.com": { + "domain": "ourblogthing.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "outgoinggiraffe.com": { + "domain": "outgoinggiraffe.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "outsidevibe.com": { + "domain": "outsidevibe.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "outstandingincome.com": { + "domain": "outstandingincome.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "outstandingsnails.com": { + "domain": "outstandingsnails.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "overkick.com": { + "domain": "overkick.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "overratedchalk.com": { + "domain": "overratedchalk.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "owlsr.us": { + "domain": "owlsr.us", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "oxygenfuse.com": { + "domain": "oxygenfuse.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pailcrime.com": { + "domain": "pailcrime.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "painstakingpickle.com": { + "domain": "painstakingpickle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "paintpear.com": { + "domain": "paintpear.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "paleleaf.com": { + "domain": "paleleaf.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pamelarandom.com": { + "domain": "pamelarandom.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "panickycurtain.com": { + "domain": "panickycurtain.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "parallelbulb.com": { + "domain": "parallelbulb.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pardonpopular.com": { + "domain": "pardonpopular.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "parentpicture.com": { + "domain": "parentpicture.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "parsimoniouspolice.com": { + "domain": "parsimoniouspolice.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "passivepolo.com": { + "domain": "passivepolo.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pastoralroad.com": { + "domain": "pastoralroad.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pawsnug.com": { + "domain": "pawsnug.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "peacefullimit.com": { + "domain": "peacefullimit.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pedromister.com": { + "domain": "pedromister.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pedropanther.com": { + "domain": "pedropanther.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "perceivequarter.com": { + "domain": "perceivequarter.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "perkyjade.com": { + "domain": "perkyjade.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "petiteumbrella.com": { + "domain": "petiteumbrella.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "philippinch.com": { + "domain": "philippinch.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "photographpan.com": { + "domain": "photographpan.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "piespower.com": { + "domain": "piespower.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "piquantgrove.com": { + "domain": "piquantgrove.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "piquantmeadow.com": { + "domain": "piquantmeadow.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "piquantpigs.com": { + "domain": "piquantpigs.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "piquantprice.com": { + "domain": "piquantprice.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "piquantvortex.com": { + "domain": "piquantvortex.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pixeledhub.com": { + "domain": "pixeledhub.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pizzasnut.com": { + "domain": "pizzasnut.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "placeframe.com": { + "domain": "placeframe.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "placidactivity.com": { + "domain": "placidactivity.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "planebasin.com": { + "domain": "planebasin.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "plantdigestion.com": { + "domain": "plantdigestion.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "playfulriver.com": { + "domain": "playfulriver.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "plotparent.com": { + "domain": "plotparent.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pluckyzone.com": { + "domain": "pluckyzone.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "poeticpackage.com": { + "domain": "poeticpackage.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pointdigestion.com": { + "domain": "pointdigestion.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pointlesshour.com": { + "domain": "pointlesshour.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pointlesspocket.com": { + "domain": "pointlesspocket.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pointlessprofit.com": { + "domain": "pointlessprofit.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pointlessrifle.com": { + "domain": "pointlessrifle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "polarismagnet.com": { + "domain": "polarismagnet.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "polishedcrescent.com": { + "domain": "polishedcrescent.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "polishedfolly.com": { + "domain": "polishedfolly.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "politeplanes.com": { + "domain": "politeplanes.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "politicalflip.com": { + "domain": "politicalflip.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "politicalporter.com": { + "domain": "politicalporter.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "popplantation.com": { + "domain": "popplantation.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "possiblepencil.com": { + "domain": "possiblepencil.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "powderjourney.com": { + "domain": "powderjourney.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "powerfulblends.com": { + "domain": "powerfulblends.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "preciousplanes.com": { + "domain": "preciousplanes.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "prefixpatriot.com": { + "domain": "prefixpatriot.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "presetrabbits.com": { + "domain": "presetrabbits.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "previousplayground.com": { + "domain": "previousplayground.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "previouspotato.com": { + "domain": "previouspotato.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pricklypollution.com": { + "domain": "pricklypollution.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pristinegale.com": { + "domain": "pristinegale.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "probablepartner.com": { + "domain": "probablepartner.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "processplantation.com": { + "domain": "processplantation.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "producepickle.com": { + "domain": "producepickle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "productsurfer.com": { + "domain": "productsurfer.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "profitrumour.com": { + "domain": "profitrumour.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "promiseair.com": { + "domain": "promiseair.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "proofconvert.com": { + "domain": "proofconvert.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "propertypotato.com": { + "domain": "propertypotato.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "protestcopy.com": { + "domain": "protestcopy.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "psychedelicchess.com": { + "domain": "psychedelicchess.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "publicsofa.com": { + "domain": "publicsofa.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "puffyloss.com": { + "domain": "puffyloss.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "puffypaste.com": { + "domain": "puffypaste.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "puffypull.com": { + "domain": "puffypull.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "puffypurpose.com": { + "domain": "puffypurpose.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pulsatingmeadow.com": { + "domain": "pulsatingmeadow.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pumpedpancake.com": { + "domain": "pumpedpancake.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "pumpedpurpose.com": { + "domain": "pumpedpurpose.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "punyplant.com": { + "domain": "punyplant.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "puppytooth.com": { + "domain": "puppytooth.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "purposepipe.com": { + "domain": "purposepipe.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "quacksquirrel.com": { + "domain": "quacksquirrel.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "quaintcan.com": { + "domain": "quaintcan.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "quaintlake.com": { + "domain": "quaintlake.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "quantumlagoon.com": { + "domain": "quantumlagoon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "quantumshine.com": { + "domain": "quantumshine.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "queenskart.com": { + "domain": "queenskart.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "quillkick.com": { + "domain": "quillkick.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "quirkybliss.com": { + "domain": "quirkybliss.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "quirkysugar.com": { + "domain": "quirkysugar.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "quixoticnebula.com": { + "domain": "quixoticnebula.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "rabbitbreath.com": { + "domain": "rabbitbreath.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "rabbitrifle.com": { + "domain": "rabbitrifle.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "radiantcanopy.com": { + "domain": "radiantcanopy.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "radiantlullaby.com": { + "domain": "radiantlullaby.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "railwaygiraffe.com": { + "domain": "railwaygiraffe.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "raintwig.com": { + "domain": "raintwig.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "rainyhand.com": { + "domain": "rainyhand.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "rainyrule.com": { + "domain": "rainyrule.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "rangecake.com": { + "domain": "rangecake.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "raresummer.com": { + "domain": "raresummer.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "reactjspdf.com": { + "domain": "reactjspdf.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "readingguilt.com": { + "domain": "readingguilt.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "readymoon.com": { + "domain": "readymoon.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "readysnails.com": { + "domain": "readysnails.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "realizedoor.com": { + "domain": "realizedoor.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "realizerecess.com": { + "domain": "realizerecess.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "rebelclover.com": { + "domain": "rebelclover.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "rebelhen.com": { + "domain": "rebelhen.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "rebelsubway.com": { + "domain": "rebelsubway.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "receiptcent.com": { + "domain": "receiptcent.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "receptiveink.com": { + "domain": "receptiveink.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "receptivereaction.com": { + "domain": "receptivereaction.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "recessrain.com": { + "domain": "recessrain.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "reconditeprison.com": { + "domain": "reconditeprison.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "reflectivestatement.com": { + "domain": "reflectivestatement.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "refundradar.com": { + "domain": "refundradar.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "regularplants.com": { + "domain": "regularplants.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "regulatesleet.com": { + "domain": "regulatesleet.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "relationrest.com": { + "domain": "relationrest.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "reloadphoto.com": { + "domain": "reloadphoto.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "rememberdiscussion.com": { + "domain": "rememberdiscussion.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "rentinfinity.com": { + "domain": "rentinfinity.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "replaceroute.com": { + "domain": "replaceroute.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "resonantbrush.com": { + "domain": "resonantbrush.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "respectrain.com": { + "domain": "respectrain.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "resplendentecho.com": { + "domain": "resplendentecho.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "retrievemint.com": { + "domain": "retrievemint.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "handsomelythumb.com": { - "domain": "handsomelythumb.com", + "rhetoricalactivity.com": { + "domain": "rhetoricalactivity.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "handyfield.com": { - "domain": "handyfield.com", + "rhetoricalveil.com": { + "domain": "rhetoricalveil.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "handyfireman.com": { - "domain": "handyfireman.com", + "rhymezebra.com": { + "domain": "rhymezebra.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "handyincrease.com": { - "domain": "handyincrease.com", + "rhythmrule.com": { + "domain": "rhythmrule.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "haplesshydrant.com": { - "domain": "haplesshydrant.com", + "richstring.com": { + "domain": "richstring.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "haplessland.com": { - "domain": "haplessland.com", + "rigidrobin.com": { + "domain": "rigidrobin.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "hatefulrequest.com": { - "domain": "hatefulrequest.com", + "rigidveil.com": { + "domain": "rigidveil.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "headydegree.com": { - "domain": "headydegree.com", + "rigorlab.com": { + "domain": "rigorlab.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "heartbreakingmind.com": { - "domain": "heartbreakingmind.com", + "ringplant.com": { + "domain": "ringplant.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "hearthorn.com": { - "domain": "hearthorn.com", + "ringsrecord.com": { + "domain": "ringsrecord.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "heavyplayground.com": { - "domain": "heavyplayground.com", + "ritzykey.com": { + "domain": "ritzykey.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "helpcollar.com": { - "domain": "helpcollar.com", + "ritzyrepresentative.com": { + "domain": "ritzyrepresentative.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "highfalutinhoney.com": { - "domain": "highfalutinhoney.com", + "ritzyveil.com": { + "domain": "ritzyveil.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "historicalbeam.com": { - "domain": "historicalbeam.com", + "rockpebbles.com": { + "domain": "rockpebbles.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "honeybulb.com": { - "domain": "honeybulb.com", + "rollconnection.com": { + "domain": "rollconnection.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "horsenectar.com": { - "domain": "horsenectar.com", + "roofrelation.com": { + "domain": "roofrelation.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "hospitablehall.com": { - "domain": "hospitablehall.com", + "roseincome.com": { + "domain": "roseincome.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "hospitablehat.com": { - "domain": "hospitablehat.com", + "rottenray.com": { + "domain": "rottenray.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "humdrumtouch.com": { - "domain": "humdrumtouch.com", + "rusticprice.com": { + "domain": "rusticprice.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "hystericalcloth.com": { - "domain": "hystericalcloth.com", + "ruthlessdegree.com": { + "domain": "ruthlessdegree.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "idyllicjazz.com": { - "domain": "idyllicjazz.com", + "ruthlessmilk.com": { + "domain": "ruthlessmilk.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "illinvention.com": { - "domain": "illinvention.com", + "sableloss.com": { + "domain": "sableloss.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "importantmeat.com": { - "domain": "importantmeat.com", + "sablesmile.com": { + "domain": "sablesmile.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "impossibleexpansion.com": { - "domain": "impossibleexpansion.com", + "sadloaf.com": { + "domain": "sadloaf.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "impulsejewel.com": { - "domain": "impulsejewel.com", + "saffronrefuge.com": { + "domain": "saffronrefuge.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "impulselumber.com": { - "domain": "impulselumber.com", + "sagargift.com": { + "domain": "sagargift.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "incompetentjoke.com": { - "domain": "incompetentjoke.com", + "saltsacademy.com": { + "domain": "saltsacademy.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "inconclusiveaction.com": { - "domain": "inconclusiveaction.com", + "samesticks.com": { + "domain": "samesticks.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "inputicicle.com": { - "domain": "inputicicle.com", + "samplesamba.com": { + "domain": "samplesamba.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "inquisitiveice.com": { - "domain": "inquisitiveice.com", + "scarcecard.com": { + "domain": "scarcecard.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "intelligentscissors.com": { - "domain": "intelligentscissors.com", + "scarceshock.com": { + "domain": "scarceshock.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "internalcondition.com": { - "domain": "internalcondition.com", + "scarcesign.com": { + "domain": "scarcesign.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "internalsink.com": { - "domain": "internalsink.com", + "scarcestructure.com": { + "domain": "scarcestructure.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "irritatingfog.com": { - "domain": "irritatingfog.com", + "scarcesurprise.com": { + "domain": "scarcesurprise.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "jollylens.com": { - "domain": "jollylens.com", + "scaredcomfort.com": { + "domain": "scaredcomfort.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "joyfulkeen.com": { - "domain": "joyfulkeen.com", + "scaredsidewalk.com": { + "domain": "scaredsidewalk.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "jubilantaura.com": { - "domain": "jubilantaura.com", + "scaredslip.com": { + "domain": "scaredslip.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "jubilantcanyon.com": { - "domain": "jubilantcanyon.com", + "scaredsnake.com": { + "domain": "scaredsnake.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "jubilantcascade.com": { - "domain": "jubilantcascade.com", + "scaredswing.com": { + "domain": "scaredswing.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "jubilantglimmer.com": { - "domain": "jubilantglimmer.com", + "scarefowl.com": { + "domain": "scarefowl.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "jubilanttempest.com": { - "domain": "jubilanttempest.com", + "scatteredheat.com": { + "domain": "scatteredheat.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "jubilantwhisper.com": { - "domain": "jubilantwhisper.com", + "scatteredquiver.com": { + "domain": "scatteredquiver.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "kaputquill.com": { - "domain": "kaputquill.com", + "scatteredstream.com": { + "domain": "scatteredstream.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "keenquill.com": { - "domain": "keenquill.com", + "scenicapparel.com": { + "domain": "scenicapparel.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "knitstamp.com": { - "domain": "knitstamp.com", + "scientificshirt.com": { + "domain": "scientificshirt.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "lameletters.com": { - "domain": "lameletters.com", + "scintillatingscissors.com": { + "domain": "scintillatingscissors.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "largebrass.com": { - "domain": "largebrass.com", + "scissorsstatement.com": { + "domain": "scissorsstatement.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "leftliquid.com": { - "domain": "leftliquid.com", + "scrapesleep.com": { + "domain": "scrapesleep.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "liftedknowledge.com": { - "domain": "liftedknowledge.com", + "scratchsofa.com": { + "domain": "scratchsofa.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "lightenafterthought.com": { - "domain": "lightenafterthought.com", + "screechingfurniture.com": { + "domain": "screechingfurniture.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "lighttalon.com": { - "domain": "lighttalon.com", + "screechingstocking.com": { + "domain": "screechingstocking.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "livelumber.com": { - "domain": "livelumber.com", + "scribbleson.com": { + "domain": "scribbleson.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "livelylaugh.com": { - "domain": "livelylaugh.com", + "scrollservice.com": { + "domain": "scrollservice.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "livelyreward.com": { - "domain": "livelyreward.com", + "scrubswim.com": { + "domain": "scrubswim.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "livingsleet.com": { - "domain": "livingsleet.com", + "seashoresociety.com": { + "domain": "seashoresociety.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "lizardslaugh.com": { - "domain": "lizardslaugh.com", + "secondhandfall.com": { + "domain": "secondhandfall.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "loadsurprise.com": { - "domain": "loadsurprise.com", + "secretivesheep.com": { + "domain": "secretivesheep.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "lonelyflavor.com": { - "domain": "lonelyflavor.com", + "secretspiders.com": { + "domain": "secretspiders.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "longingtrees.com": { - "domain": "longingtrees.com", + "secretturtle.com": { + "domain": "secretturtle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "lorenzourban.com": { - "domain": "lorenzourban.com", + "seedscissors.com": { + "domain": "seedscissors.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "losslace.com": { - "domain": "losslace.com", + "seemlysuggestion.com": { + "domain": "seemlysuggestion.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ludicrousarch.com": { - "domain": "ludicrousarch.com", + "selfishsea.com": { + "domain": "selfishsea.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "luminousboulevard.com": { - "domain": "luminousboulevard.com", + "sendingspire.com": { + "domain": "sendingspire.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "luminouscatalyst.com": { - "domain": "luminouscatalyst.com", + "sensorsmile.com": { + "domain": "sensorsmile.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "lumpylumber.com": { - "domain": "lumpylumber.com", + "separatesort.com": { + "domain": "separatesort.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "lustroushaven.com": { - "domain": "lustroushaven.com", + "seraphichorizon.com": { + "domain": "seraphichorizon.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "magicaljoin.com": { - "domain": "magicaljoin.com", + "seraphicjubilee.com": { + "domain": "seraphicjubilee.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "majesticwaterscape.com": { - "domain": "majesticwaterscape.com", + "serendipityecho.com": { + "domain": "serendipityecho.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "majesticwilderness.com": { - "domain": "majesticwilderness.com", + "serenecascade.com": { + "domain": "serenecascade.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "maliciousmusic.com": { - "domain": "maliciousmusic.com", + "serenepebble.com": { + "domain": "serenepebble.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "marketspiders.com": { - "domain": "marketspiders.com", + "serenesurf.com": { + "domain": "serenesurf.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "marriedvalue.com": { - "domain": "marriedvalue.com", + "serioussuit.com": { + "domain": "serioussuit.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "materialisticmoon.com": { - "domain": "materialisticmoon.com", + "serpentshampoo.com": { + "domain": "serpentshampoo.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "materialplayground.com": { - "domain": "materialplayground.com", + "settleshoes.com": { + "domain": "settleshoes.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "meadowlullaby.com": { - "domain": "meadowlullaby.com", + "shadeship.com": { + "domain": "shadeship.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "meatydime.com": { - "domain": "meatydime.com", + "shaggytank.com": { + "domain": "shaggytank.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "melodiouschorus.com": { - "domain": "melodiouschorus.com", + "shakyseat.com": { + "domain": "shakyseat.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "melodiouscomposition.com": { - "domain": "melodiouscomposition.com", + "shakysurprise.com": { + "domain": "shakysurprise.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "meltmilk.com": { - "domain": "meltmilk.com", + "shakytaste.com": { + "domain": "shakytaste.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "memopilot.com": { - "domain": "memopilot.com", + "shallowblade.com": { + "domain": "shallowblade.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "memorizeneck.com": { - "domain": "memorizeneck.com", + "sharkskids.com": { + "domain": "sharkskids.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "meremark.com": { - "domain": "meremark.com", + "sheargovernor.com": { + "domain": "sheargovernor.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "merequartz.com": { - "domain": "merequartz.com", + "shesubscriptions.com": { + "domain": "shesubscriptions.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "merryopal.com": { - "domain": "merryopal.com", + "shinypond.com": { + "domain": "shinypond.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "merryvault.com": { - "domain": "merryvault.com", + "shirtsidewalk.com": { + "domain": "shirtsidewalk.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "mightyspiders.com": { - "domain": "mightyspiders.com", + "shiveringspot.com": { + "domain": "shiveringspot.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "minorcattle.com": { - "domain": "minorcattle.com", + "shiverscissors.com": { + "domain": "shiverscissors.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "minuteburst.com": { - "domain": "minuteburst.com", + "shockinggrass.com": { + "domain": "shockinggrass.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "mixedreading.com": { - "domain": "mixedreading.com", + "shockingship.com": { + "domain": "shockingship.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "modularmental.com": { - "domain": "modularmental.com", + "shredquiz.com": { + "domain": "shredquiz.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "monacobeatles.com": { - "domain": "monacobeatles.com", + "shydinosaurs.com": { + "domain": "shydinosaurs.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "sierrakermit.com": { + "domain": "sierrakermit.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "signaturepod.com": { + "domain": "signaturepod.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "siliconslow.com": { + "domain": "siliconslow.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "sillyscrew.com": { + "domain": "sillyscrew.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "moorshoes.com": { - "domain": "moorshoes.com", + "simplesidewalk.com": { + "domain": "simplesidewalk.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "motionlessbag.com": { - "domain": "motionlessbag.com", + "simulateswing.com": { + "domain": "simulateswing.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "motionlessmeeting.com": { - "domain": "motionlessmeeting.com", + "sincerebuffalo.com": { + "domain": "sincerebuffalo.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "movemeal.com": { - "domain": "movemeal.com", + "sincerepelican.com": { + "domain": "sincerepelican.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "mundanenail.com": { - "domain": "mundanenail.com", + "sinceresubstance.com": { + "domain": "sinceresubstance.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "mushywaste.com": { - "domain": "mushywaste.com", + "sinkbooks.com": { + "domain": "sinkbooks.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "muteknife.com": { - "domain": "muteknife.com", + "sixscissors.com": { + "domain": "sixscissors.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "mysticalagoon.com": { - "domain": "mysticalagoon.com", + "sizzlingsmoke.com": { + "domain": "sizzlingsmoke.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "naivestatement.com": { - "domain": "naivestatement.com", + "slaysweater.com": { + "domain": "slaysweater.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "neatshade.com": { - "domain": "neatshade.com", + "slimyscarf.com": { + "domain": "slimyscarf.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "nebulacrescent.com": { - "domain": "nebulacrescent.com", + "slinksuggestion.com": { + "domain": "slinksuggestion.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "nebulajubilee.com": { - "domain": "nebulajubilee.com", + "smallershops.com": { + "domain": "smallershops.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "nebulousamusement.com": { - "domain": "nebulousamusement.com", + "smashshoe.com": { + "domain": "smashshoe.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "nebulousgarden.com": { - "domain": "nebulousgarden.com", + "smilewound.com": { + "domain": "smilewound.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "nebulousquasar.com": { - "domain": "nebulousquasar.com", + "smilingcattle.com": { + "domain": "smilingcattle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "nebulousripple.com": { - "domain": "nebulousripple.com", + "smilingswim.com": { + "domain": "smilingswim.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "needlessnorth.com": { - "domain": "needlessnorth.com", + "smilingwaves.com": { + "domain": "smilingwaves.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "niftyhospital.com": { - "domain": "niftyhospital.com", + "smoggysongs.com": { + "domain": "smoggysongs.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "nightwound.com": { - "domain": "nightwound.com", + "smoggystation.com": { + "domain": "smoggystation.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "nocturnalloom.com": { - "domain": "nocturnalloom.com", + "snacktoken.com": { + "domain": "snacktoken.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "nondescriptcrowd.com": { - "domain": "nondescriptcrowd.com", + "snakemineral.com": { + "domain": "snakemineral.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "nostalgicneed.com": { - "domain": "nostalgicneed.com", + "snakeslang.com": { + "domain": "snakeslang.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "numberlessring.com": { - "domain": "numberlessring.com", + "sneakwind.com": { + "domain": "sneakwind.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "nuttyorganization.com": { - "domain": "nuttyorganization.com", + "sneakystew.com": { + "domain": "sneakystew.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "oafishchance.com": { - "domain": "oafishchance.com", + "snoresmile.com": { + "domain": "snoresmile.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "obscenesidewalk.com": { - "domain": "obscenesidewalk.com", + "snowmentor.com": { + "domain": "snowmentor.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "oldfashionedoffer.com": { - "domain": "oldfashionedoffer.com", + "soggysponge.com": { + "domain": "soggysponge.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "opalquill.com": { - "domain": "opalquill.com", + "soggyzoo.com": { + "domain": "soggyzoo.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "operationchicken.com": { - "domain": "operationchicken.com", + "solarislabyrinth.com": { + "domain": "solarislabyrinth.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "optimallimit.com": { - "domain": "optimallimit.com", + "somberscarecrow.com": { + "domain": "somberscarecrow.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "opulentsylvan.com": { - "domain": "opulentsylvan.com", + "sombersea.com": { + "domain": "sombersea.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "orientedargument.com": { - "domain": "orientedargument.com", + "sombersquirrel.com": { + "domain": "sombersquirrel.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "outstandingincome.com": { - "domain": "outstandingincome.com", + "sombersticks.com": { + "domain": "sombersticks.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "outstandingsnails.com": { - "domain": "outstandingsnails.com", + "sombersurprise.com": { + "domain": "sombersurprise.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "painstakingpickle.com": { - "domain": "painstakingpickle.com", + "soothingglade.com": { + "domain": "soothingglade.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "pamelarandom.com": { - "domain": "pamelarandom.com", + "sophisticatedstove.com": { + "domain": "sophisticatedstove.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "panickycurtain.com": { - "domain": "panickycurtain.com", + "sordidsmile.com": { + "domain": "sordidsmile.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "parallelbulb.com": { - "domain": "parallelbulb.com", + "soresidewalk.com": { + "domain": "soresidewalk.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "parentpicture.com": { - "domain": "parentpicture.com", + "soresneeze.com": { + "domain": "soresneeze.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "passivepolo.com": { - "domain": "passivepolo.com", + "sorethunder.com": { + "domain": "sorethunder.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "peacefullimit.com": { - "domain": "peacefullimit.com", + "soretrain.com": { + "domain": "soretrain.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "petiteumbrella.com": { - "domain": "petiteumbrella.com", + "sortsail.com": { + "domain": "sortsail.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "piquantgrove.com": { - "domain": "piquantgrove.com", + "sortsummer.com": { + "domain": "sortsummer.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "piquantmeadow.com": { - "domain": "piquantmeadow.com", + "sowlettuce.com": { + "domain": "sowlettuce.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "piquantvortex.com": { - "domain": "piquantvortex.com", + "spadelocket.com": { + "domain": "spadelocket.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "placidactivity.com": { - "domain": "placidactivity.com", + "sparkgoal.com": { + "domain": "sparkgoal.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "planebasin.com": { - "domain": "planebasin.com", + "sparklingshelf.com": { + "domain": "sparklingshelf.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "plantdigestion.com": { - "domain": "plantdigestion.com", + "specialscissors.com": { + "domain": "specialscissors.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "playfulriver.com": { - "domain": "playfulriver.com", + "spellmist.com": { + "domain": "spellmist.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "pluckyzone.com": { - "domain": "pluckyzone.com", + "spellsalsa.com": { + "domain": "spellsalsa.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "poeticpackage.com": { - "domain": "poeticpackage.com", + "spiffymachine.com": { + "domain": "spiffymachine.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "pointdigestion.com": { - "domain": "pointdigestion.com", + "spirebaboon.com": { + "domain": "spirebaboon.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "pointlesspocket.com": { - "domain": "pointlesspocket.com", + "spookystitch.com": { + "domain": "spookystitch.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "pointlessprofit.com": { - "domain": "pointlessprofit.com", + "spoonsilk.com": { + "domain": "spoonsilk.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "polishedcrescent.com": { - "domain": "polishedcrescent.com", + "spotlessstamp.com": { + "domain": "spotlessstamp.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "polishedfolly.com": { - "domain": "polishedfolly.com", + "spottednoise.com": { + "domain": "spottednoise.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "politeplanes.com": { - "domain": "politeplanes.com", + "springolive.com": { + "domain": "springolive.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "politicalporter.com": { - "domain": "politicalporter.com", + "springsister.com": { + "domain": "springsister.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "popplantation.com": { - "domain": "popplantation.com", + "springsnails.com": { + "domain": "springsnails.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "possiblepencil.com": { - "domain": "possiblepencil.com", + "sproutingbag.com": { + "domain": "sproutingbag.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "powderjourney.com": { - "domain": "powderjourney.com", + "sprydelta.com": { + "domain": "sprydelta.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "preciousplanes.com": { - "domain": "preciousplanes.com", + "sprysummit.com": { + "domain": "sprysummit.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "pricklypollution.com": { - "domain": "pricklypollution.com", + "spuriousair.com": { + "domain": "spuriousair.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "pristinegale.com": { - "domain": "pristinegale.com", + "spuriousbase.com": { + "domain": "spuriousbase.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "processplantation.com": { - "domain": "processplantation.com", + "spurioussquirrel.com": { + "domain": "spurioussquirrel.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "protestcopy.com": { - "domain": "protestcopy.com", + "spuriousstranger.com": { + "domain": "spuriousstranger.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "publicsofa.com": { - "domain": "publicsofa.com", + "spysubstance.com": { + "domain": "spysubstance.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "puffypurpose.com": { - "domain": "puffypurpose.com", + "squalidscrew.com": { + "domain": "squalidscrew.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "pulsatingmeadow.com": { - "domain": "pulsatingmeadow.com", + "squeakzinc.com": { + "domain": "squeakzinc.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "pumpedpancake.com": { - "domain": "pumpedpancake.com", + "squealingturn.com": { + "domain": "squealingturn.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "punyplant.com": { - "domain": "punyplant.com", + "stakingbasket.com": { + "domain": "stakingbasket.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "purposepipe.com": { - "domain": "purposepipe.com", + "stakingshock.com": { + "domain": "stakingshock.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "quaintlake.com": { - "domain": "quaintlake.com", + "staleshow.com": { + "domain": "staleshow.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "quillkick.com": { - "domain": "quillkick.com", + "stalesummer.com": { + "domain": "stalesummer.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "quirkybliss.com": { - "domain": "quirkybliss.com", + "starkscale.com": { + "domain": "starkscale.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "quirkysugar.com": { - "domain": "quirkysugar.com", + "startingcars.com": { + "domain": "startingcars.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rabbitbreath.com": { - "domain": "rabbitbreath.com", + "statshunt.com": { + "domain": "statshunt.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rabbitrifle.com": { - "domain": "rabbitrifle.com", + "statuesqueship.com": { + "domain": "statuesqueship.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "radiantlullaby.com": { - "domain": "radiantlullaby.com", + "stayaction.com": { + "domain": "stayaction.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "railwaygiraffe.com": { - "domain": "railwaygiraffe.com", + "steadycopper.com": { + "domain": "steadycopper.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "raintwig.com": { - "domain": "raintwig.com", + "stealsteel.com": { + "domain": "stealsteel.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rainyhand.com": { - "domain": "rainyhand.com", + "steepscale.com": { + "domain": "steepscale.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rainyrule.com": { - "domain": "rainyrule.com", + "steepsister.com": { + "domain": "steepsister.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rangecake.com": { - "domain": "rangecake.com", + "stepcattle.com": { + "domain": "stepcattle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "raresummer.com": { - "domain": "raresummer.com", + "stepplane.com": { + "domain": "stepplane.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "readymoon.com": { - "domain": "readymoon.com", + "stepwisevideo.com": { + "domain": "stepwisevideo.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rebelhen.com": { - "domain": "rebelhen.com", + "stereoproxy.com": { + "domain": "stereoproxy.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rebelsubway.com": { - "domain": "rebelsubway.com", + "stewspiders.com": { + "domain": "stewspiders.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "receptivereaction.com": { - "domain": "receptivereaction.com", + "stiffstem.com": { + "domain": "stiffstem.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "recessrain.com": { - "domain": "recessrain.com", + "stimulatingsneeze.com": { + "domain": "stimulatingsneeze.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "reconditeprison.com": { - "domain": "reconditeprison.com", + "stingsquirrel.com": { + "domain": "stingsquirrel.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "reflectivestatement.com": { - "domain": "reflectivestatement.com", + "stingyshoe.com": { + "domain": "stingyshoe.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "regularplants.com": { - "domain": "regularplants.com", + "stingyspoon.com": { + "domain": "stingyspoon.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "regulatesleet.com": { - "domain": "regulatesleet.com", + "stockingsleet.com": { + "domain": "stockingsleet.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "relationrest.com": { - "domain": "relationrest.com", + "stockingsneeze.com": { + "domain": "stockingsneeze.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rememberdiscussion.com": { - "domain": "rememberdiscussion.com", + "stomachscience.com": { + "domain": "stomachscience.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "replaceroute.com": { - "domain": "replaceroute.com", + "stonechin.com": { + "domain": "stonechin.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "resonantbrush.com": { - "domain": "resonantbrush.com", + "stopstomach.com": { + "domain": "stopstomach.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "respectrain.com": { - "domain": "respectrain.com", + "stormyachiever.com": { + "domain": "stormyachiever.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "resplendentecho.com": { - "domain": "resplendentecho.com", + "stormyfold.com": { + "domain": "stormyfold.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "retrievemint.com": { - "domain": "retrievemint.com", + "strangeclocks.com": { + "domain": "strangeclocks.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rhetoricalveil.com": { - "domain": "rhetoricalveil.com", + "strangersponge.com": { + "domain": "strangersponge.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rhymezebra.com": { - "domain": "rhymezebra.com", + "strangesink.com": { + "domain": "strangesink.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "richstring.com": { - "domain": "richstring.com", + "streetsort.com": { + "domain": "streetsort.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rigidrobin.com": { - "domain": "rigidrobin.com", + "stretchsister.com": { + "domain": "stretchsister.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rigidveil.com": { - "domain": "rigidveil.com", + "stretchsneeze.com": { + "domain": "stretchsneeze.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ringplant.com": { - "domain": "ringplant.com", + "stretchsquirrel.com": { + "domain": "stretchsquirrel.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rollconnection.com": { - "domain": "rollconnection.com", + "stripedbat.com": { + "domain": "stripedbat.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "roofrelation.com": { - "domain": "roofrelation.com", + "strivesidewalk.com": { + "domain": "strivesidewalk.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "roseincome.com": { - "domain": "roseincome.com", + "sturdysnail.com": { + "domain": "sturdysnail.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "rusticprice.com": { - "domain": "rusticprice.com", + "subletyoke.com": { + "domain": "subletyoke.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sadloaf.com": { - "domain": "sadloaf.com", + "sublimequartz.com": { + "domain": "sublimequartz.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "samesticks.com": { - "domain": "samesticks.com", + "subsequentswim.com": { + "domain": "subsequentswim.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "samplesamba.com": { - "domain": "samplesamba.com", + "substantialcarpenter.com": { + "domain": "substantialcarpenter.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scarceshock.com": { - "domain": "scarceshock.com", + "substantialgrade.com": { + "domain": "substantialgrade.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scarcestructure.com": { - "domain": "scarcestructure.com", + "succeedscene.com": { + "domain": "succeedscene.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scaredcomfort.com": { - "domain": "scaredcomfort.com", + "successfulscent.com": { + "domain": "successfulscent.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scaredslip.com": { - "domain": "scaredslip.com", + "suddensoda.com": { + "domain": "suddensoda.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scaredsnake.com": { - "domain": "scaredsnake.com", + "sugarfriction.com": { + "domain": "sugarfriction.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scarefowl.com": { - "domain": "scarefowl.com", + "suggestionbridge.com": { + "domain": "suggestionbridge.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scatteredstream.com": { - "domain": "scatteredstream.com", + "summerobject.com": { + "domain": "summerobject.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scientificshirt.com": { - "domain": "scientificshirt.com", + "sunshinegates.com": { + "domain": "sunshinegates.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scintillatingscissors.com": { - "domain": "scintillatingscissors.com", + "superchichair.com": { + "domain": "superchichair.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scissorsstatement.com": { - "domain": "scissorsstatement.com", + "superficialspring.com": { + "domain": "superficialspring.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scrapesleep.com": { - "domain": "scrapesleep.com", + "superviseshoes.com": { + "domain": "superviseshoes.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "screechingfurniture.com": { - "domain": "screechingfurniture.com", + "supportwaves.com": { + "domain": "supportwaves.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "screechingstocking.com": { - "domain": "screechingstocking.com", + "suspectmark.com": { + "domain": "suspectmark.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "scribbleson.com": { - "domain": "scribbleson.com", + "swellstocking.com": { + "domain": "swellstocking.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "seashoresociety.com": { - "domain": "seashoresociety.com", + "swelteringsleep.com": { + "domain": "swelteringsleep.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "secondhandfall.com": { - "domain": "secondhandfall.com", + "swingslip.com": { + "domain": "swingslip.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "secretturtle.com": { - "domain": "secretturtle.com", + "swordgoose.com": { + "domain": "swordgoose.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "seemlysuggestion.com": { - "domain": "seemlysuggestion.com", + "syllablesight.com": { + "domain": "syllablesight.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "separatesort.com": { - "domain": "separatesort.com", + "synonymousrule.com": { + "domain": "synonymousrule.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "seraphicjubilee.com": { - "domain": "seraphicjubilee.com", + "synonymoussticks.com": { + "domain": "synonymoussticks.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "serenecascade.com": { - "domain": "serenecascade.com", + "synthesizescarecrow.com": { + "domain": "synthesizescarecrow.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "serenepebble.com": { - "domain": "serenepebble.com", + "tackytrains.com": { + "domain": "tackytrains.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "serenesurf.com": { - "domain": "serenesurf.com", + "tacojournal.com": { + "domain": "tacojournal.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "serioussuit.com": { - "domain": "serioussuit.com", + "talltouch.com": { + "domain": "talltouch.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "serpentshampoo.com": { - "domain": "serpentshampoo.com", + "tangibleteam.com": { + "domain": "tangibleteam.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "settleshoes.com": { - "domain": "settleshoes.com", + "tangyamount.com": { + "domain": "tangyamount.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "shadeship.com": { - "domain": "shadeship.com", + "tastelesstrees.com": { + "domain": "tastelesstrees.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "shakyseat.com": { - "domain": "shakyseat.com", + "tastelesstrucks.com": { + "domain": "tastelesstrucks.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "shakysurprise.com": { - "domain": "shakysurprise.com", + "tastesnake.com": { + "domain": "tastesnake.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "shallowblade.com": { - "domain": "shallowblade.com", + "tawdryson.com": { + "domain": "tawdryson.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sheargovernor.com": { - "domain": "sheargovernor.com", + "tdzvm.pw": { + "domain": "tdzvm.pw", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "shesubscriptions.com": { - "domain": "shesubscriptions.com", + "tearfulglass.com": { + "domain": "tearfulglass.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "shinypond.com": { - "domain": "shinypond.com", + "techconverter.com": { + "domain": "techconverter.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "shirtsidewalk.com": { - "domain": "shirtsidewalk.com", + "tediousbear.com": { + "domain": "tediousbear.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "shiveringspot.com": { - "domain": "shiveringspot.com", + "tedioustooth.com": { + "domain": "tedioustooth.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "shiverscissors.com": { - "domain": "shiverscissors.com", + "teenytinycellar.com": { + "domain": "teenytinycellar.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "shockingship.com": { - "domain": "shockingship.com", + "teenytinytongue.com": { + "domain": "teenytinytongue.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sierrakermit.com": { - "domain": "sierrakermit.com", + "telephoneapparatus.com": { + "domain": "telephoneapparatus.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sillyscrew.com": { - "domain": "sillyscrew.com", + "tempertrick.com": { + "domain": "tempertrick.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "simulateswing.com": { - "domain": "simulateswing.com", + "tempttalk.com": { + "domain": "tempttalk.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sincerebuffalo.com": { - "domain": "sincerebuffalo.com", + "temptteam.com": { + "domain": "temptteam.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sincerepelican.com": { - "domain": "sincerepelican.com", + "terriblethumb.com": { + "domain": "terriblethumb.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sinceresubstance.com": { - "domain": "sinceresubstance.com", + "terrifictooth.com": { + "domain": "terrifictooth.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sinkbooks.com": { - "domain": "sinkbooks.com", + "testadmiral.com": { + "domain": "testadmiral.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sixscissors.com": { - "domain": "sixscissors.com", + "texturetrick.com": { + "domain": "texturetrick.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "slinksuggestion.com": { - "domain": "slinksuggestion.com", + "therapeuticcars.com": { + "domain": "therapeuticcars.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "smilingswim.com": { - "domain": "smilingswim.com", + "thickticket.com": { + "domain": "thickticket.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "smoggysongs.com": { - "domain": "smoggysongs.com", + "thicktrucks.com": { + "domain": "thicktrucks.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sneakwind.com": { - "domain": "sneakwind.com", + "thingsafterthought.com": { + "domain": "thingsafterthought.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "soggysponge.com": { - "domain": "soggysponge.com", + "thingstaste.com": { + "domain": "thingstaste.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "soggyzoo.com": { - "domain": "soggyzoo.com", + "thinkitwice.com": { + "domain": "thinkitwice.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "solarislabyrinth.com": { - "domain": "solarislabyrinth.com", + "thirdrespect.com": { + "domain": "thirdrespect.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "somberscarecrow.com": { - "domain": "somberscarecrow.com", + "thirstytwig.com": { + "domain": "thirstytwig.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sombersticks.com": { - "domain": "sombersticks.com", + "thomastorch.com": { + "domain": "thomastorch.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "soothingglade.com": { - "domain": "soothingglade.com", + "thoughtlessknot.com": { + "domain": "thoughtlessknot.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sordidsmile.com": { - "domain": "sordidsmile.com", + "thrivingmarketplace.com": { + "domain": "thrivingmarketplace.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "soresidewalk.com": { - "domain": "soresidewalk.com", + "ticketaunt.com": { + "domain": "ticketaunt.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "soretrain.com": { - "domain": "soretrain.com", + "ticklesign.com": { + "domain": "ticklesign.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sortsail.com": { - "domain": "sortsail.com", + "tidymitten.com": { + "domain": "tidymitten.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sortsummer.com": { - "domain": "sortsummer.com", + "tightpowder.com": { + "domain": "tightpowder.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "spellmist.com": { - "domain": "spellmist.com", + "tinyswans.com": { + "domain": "tinyswans.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "spellsalsa.com": { - "domain": "spellsalsa.com", + "tinytendency.com": { + "domain": "tinytendency.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "spotlessstamp.com": { - "domain": "spotlessstamp.com", + "tiredthroat.com": { + "domain": "tiredthroat.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "spottednoise.com": { - "domain": "spottednoise.com", + "toolcapital.com": { + "domain": "toolcapital.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sprysummit.com": { - "domain": "sprysummit.com", + "toomanyalts.com": { + "domain": "toomanyalts.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "spuriousair.com": { - "domain": "spuriousair.com", + "torpidtongue.com": { + "domain": "torpidtongue.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "spysubstance.com": { - "domain": "spysubstance.com", + "trackcaddie.com": { + "domain": "trackcaddie.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "squalidscrew.com": { - "domain": "squalidscrew.com", + "tradetooth.com": { + "domain": "tradetooth.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stakingbasket.com": { - "domain": "stakingbasket.com", + "trafficviews.com": { + "domain": "trafficviews.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stakingshock.com": { - "domain": "stakingshock.com", + "tranquilamulet.com": { + "domain": "tranquilamulet.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stalesummer.com": { - "domain": "stalesummer.com", + "tranquilarchipelago.com": { + "domain": "tranquilarchipelago.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "statuesqueship.com": { - "domain": "statuesqueship.com", + "tranquilcan.com": { + "domain": "tranquilcan.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "steadycopper.com": { - "domain": "steadycopper.com", + "tranquilcanyon.com": { + "domain": "tranquilcanyon.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stealsteel.com": { - "domain": "stealsteel.com", + "tranquilplume.com": { + "domain": "tranquilplume.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "steepscale.com": { - "domain": "steepscale.com", + "tranquilside.com": { + "domain": "tranquilside.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stepplane.com": { - "domain": "stepplane.com", + "tranquilveil.com": { + "domain": "tranquilveil.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stereoproxy.com": { - "domain": "stereoproxy.com", + "tranquilveranda.com": { + "domain": "tranquilveranda.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stimulatingsneeze.com": { - "domain": "stimulatingsneeze.com", + "trappush.com": { + "domain": "trappush.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stingyshoe.com": { - "domain": "stingyshoe.com", + "treadbun.com": { + "domain": "treadbun.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stingyspoon.com": { - "domain": "stingyspoon.com", + "tremendousearthquake.com": { + "domain": "tremendousearthquake.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stockingsleet.com": { - "domain": "stockingsleet.com", + "tremendousplastic.com": { + "domain": "tremendousplastic.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stomachscience.com": { - "domain": "stomachscience.com", + "tremendoustime.com": { + "domain": "tremendoustime.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stopstomach.com": { - "domain": "stopstomach.com", + "tritebadge.com": { + "domain": "tritebadge.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stormyfold.com": { - "domain": "stormyfold.com", + "tritethunder.com": { + "domain": "tritethunder.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "strangeclocks.com": { - "domain": "strangeclocks.com", + "tritetongue.com": { + "domain": "tritetongue.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "strangersponge.com": { - "domain": "strangersponge.com", + "troubledtail.com": { + "domain": "troubledtail.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "strangesink.com": { - "domain": "strangesink.com", + "troubleshade.com": { + "domain": "troubleshade.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stretchsister.com": { - "domain": "stretchsister.com", + "truckstomatoes.com": { + "domain": "truckstomatoes.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stretchsneeze.com": { - "domain": "stretchsneeze.com", + "truculentrate.com": { + "domain": "truculentrate.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stretchsquirrel.com": { - "domain": "stretchsquirrel.com", + "tumbleicicle.com": { + "domain": "tumbleicicle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "stripedbat.com": { - "domain": "stripedbat.com", + "tuneupcoffee.com": { + "domain": "tuneupcoffee.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "strivesidewalk.com": { - "domain": "strivesidewalk.com", + "twistloss.com": { + "domain": "twistloss.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sublimequartz.com": { - "domain": "sublimequartz.com", + "twistsweater.com": { + "domain": "twistsweater.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "succeedscene.com": { - "domain": "succeedscene.com", + "typicalairplane.com": { + "domain": "typicalairplane.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "sugarfriction.com": { - "domain": "sugarfriction.com", + "tzwaw.pw": { + "domain": "tzwaw.pw", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "suggestionbridge.com": { - "domain": "suggestionbridge.com", + "ubiquitoussea.com": { + "domain": "ubiquitoussea.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "superficialspring.com": { - "domain": "superficialspring.com", + "ubiquitousyard.com": { + "domain": "ubiquitousyard.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "supportwaves.com": { - "domain": "supportwaves.com", + "ultravalid.com": { + "domain": "ultravalid.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "suspectmark.com": { - "domain": "suspectmark.com", + "unablehope.com": { + "domain": "unablehope.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "swellstocking.com": { - "domain": "swellstocking.com", + "unaccountablecreator.com": { + "domain": "unaccountablecreator.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "swelteringsleep.com": { - "domain": "swelteringsleep.com", + "unaccountablepie.com": { + "domain": "unaccountablepie.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "swingslip.com": { - "domain": "swingslip.com", + "unarmedindustry.com": { + "domain": "unarmedindustry.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "synonymousrule.com": { - "domain": "synonymousrule.com", + "unbecominghall.com": { + "domain": "unbecominghall.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "synonymoussticks.com": { - "domain": "synonymoussticks.com", + "uncoveredexpert.com": { + "domain": "uncoveredexpert.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "synthesizescarecrow.com": { - "domain": "synthesizescarecrow.com", + "understoodocean.com": { + "domain": "understoodocean.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tackytrains.com": { - "domain": "tackytrains.com", + "unequalbrake.com": { + "domain": "unequalbrake.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tangyamount.com": { - "domain": "tangyamount.com", + "unequaltrail.com": { + "domain": "unequaltrail.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tastelesstrees.com": { - "domain": "tastelesstrees.com", + "unknowncontrol.com": { + "domain": "unknowncontrol.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tastelesstrucks.com": { - "domain": "tastelesstrucks.com", + "unknowncrate.com": { + "domain": "unknowncrate.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tearfulglass.com": { - "domain": "tearfulglass.com", + "unknowntray.com": { + "domain": "unknowntray.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "teenytinycellar.com": { - "domain": "teenytinycellar.com", + "untidyquestion.com": { + "domain": "untidyquestion.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "teenytinytongue.com": { - "domain": "teenytinytongue.com", + "untidyrice.com": { + "domain": "untidyrice.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tempertrick.com": { - "domain": "tempertrick.com", + "unusedstone.com": { + "domain": "unusedstone.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "temptteam.com": { - "domain": "temptteam.com", + "unusualtitle.com": { + "domain": "unusualtitle.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "terriblethumb.com": { - "domain": "terriblethumb.com", + "unwieldyimpulse.com": { + "domain": "unwieldyimpulse.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "terrifictooth.com": { - "domain": "terrifictooth.com", + "uppitytime.com": { + "domain": "uppitytime.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "thingstaste.com": { - "domain": "thingstaste.com", + "uselesslumber.com": { + "domain": "uselesslumber.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "thirdrespect.com": { - "domain": "thirdrespect.com", + "validmemo.com": { + "domain": "validmemo.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "thomastorch.com": { - "domain": "thomastorch.com", + "vanfireworks.com": { + "domain": "vanfireworks.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "thoughtlessknot.com": { - "domain": "thoughtlessknot.com", + "vanishmemory.com": { + "domain": "vanishmemory.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "thrivingmarketplace.com": { - "domain": "thrivingmarketplace.com", + "velvetnova.com": { + "domain": "velvetnova.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ticketaunt.com": { - "domain": "ticketaunt.com", + "velvetquasar.com": { + "domain": "velvetquasar.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tidymitten.com": { - "domain": "tidymitten.com", + "venomousvessel.com": { + "domain": "venomousvessel.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tiredthroat.com": { - "domain": "tiredthroat.com", + "venusgloria.com": { + "domain": "venusgloria.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tradetooth.com": { - "domain": "tradetooth.com", + "verdantanswer.com": { + "domain": "verdantanswer.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tranquilcan.com": { - "domain": "tranquilcan.com", + "verdantlabyrinth.com": { + "domain": "verdantlabyrinth.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tranquilcanyon.com": { - "domain": "tranquilcanyon.com", + "verdantloom.com": { + "domain": "verdantloom.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tranquilplume.com": { - "domain": "tranquilplume.com", + "verdantsculpture.com": { + "domain": "verdantsculpture.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tranquilveil.com": { - "domain": "tranquilveil.com", + "verseballs.com": { + "domain": "verseballs.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tranquilveranda.com": { - "domain": "tranquilveranda.com", + "vibrantcelebration.com": { + "domain": "vibrantcelebration.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tremendousearthquake.com": { - "domain": "tremendousearthquake.com", + "vibrantgale.com": { + "domain": "vibrantgale.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tremendousplastic.com": { - "domain": "tremendousplastic.com", + "vibranthaven.com": { + "domain": "vibranthaven.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tritebadge.com": { - "domain": "tritebadge.com", + "vibrantpact.com": { + "domain": "vibrantpact.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tritethunder.com": { - "domain": "tritethunder.com", + "vibrantsundown.com": { + "domain": "vibrantsundown.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "troubledtail.com": { - "domain": "troubledtail.com", + "vibranttalisman.com": { + "domain": "vibranttalisman.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "troubleshade.com": { - "domain": "troubleshade.com", + "vibrantvale.com": { + "domain": "vibrantvale.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "truculentrate.com": { - "domain": "truculentrate.com", + "victoriousrequest.com": { + "domain": "victoriousrequest.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "tumbleicicle.com": { - "domain": "tumbleicicle.com", + "virtualvincent.com": { + "domain": "virtualvincent.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "typicalairplane.com": { - "domain": "typicalairplane.com", + "vividcanopy.com": { + "domain": "vividcanopy.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ubiquitoussea.com": { - "domain": "ubiquitoussea.com", + "vividfrost.com": { + "domain": "vividfrost.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "ubiquitousyard.com": { - "domain": "ubiquitousyard.com", + "vividmeadow.com": { + "domain": "vividmeadow.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "unablehope.com": { - "domain": "unablehope.com", + "vividplume.com": { + "domain": "vividplume.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "unaccountablepie.com": { - "domain": "unaccountablepie.com", + "voicelessvein.com": { + "domain": "voicelessvein.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "unbecominghall.com": { - "domain": "unbecominghall.com", + "voidgoo.com": { + "domain": "voidgoo.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "uncoveredexpert.com": { - "domain": "uncoveredexpert.com", + "volatileprofit.com": { + "domain": "volatileprofit.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "unequalbrake.com": { - "domain": "unequalbrake.com", + "vq1qi.pw": { + "domain": "vq1qi.pw", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "unequaltrail.com": { - "domain": "unequaltrail.com", + "waitingnumber.com": { + "domain": "waitingnumber.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "unknowncrate.com": { - "domain": "unknowncrate.com", + "wantingwindow.com": { + "domain": "wantingwindow.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "untidyrice.com": { - "domain": "untidyrice.com", + "warnwing.com": { + "domain": "warnwing.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "unusedstone.com": { - "domain": "unusedstone.com", + "washbanana.com": { + "domain": "washbanana.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "unwieldyimpulse.com": { - "domain": "unwieldyimpulse.com", + "wateryvan.com": { + "domain": "wateryvan.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "uppitytime.com": { - "domain": "uppitytime.com", + "waterywave.com": { + "domain": "waterywave.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "uselesslumber.com": { - "domain": "uselesslumber.com", + "waterywrist.com": { + "domain": "waterywrist.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "vanishmemory.com": { - "domain": "vanishmemory.com", + "wearbasin.com": { + "domain": "wearbasin.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "velvetquasar.com": { - "domain": "velvetquasar.com", + "websitesdude.com": { + "domain": "websitesdude.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "venomousvessel.com": { - "domain": "venomousvessel.com", + "wellgroomedapparel.com": { + "domain": "wellgroomedapparel.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "venusgloria.com": { - "domain": "venusgloria.com", + "wellgroomedhydrant.com": { + "domain": "wellgroomedhydrant.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "verdantanswer.com": { - "domain": "verdantanswer.com", + "wellmadefrog.com": { + "domain": "wellmadefrog.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "verdantlabyrinth.com": { - "domain": "verdantlabyrinth.com", + "westpalmweb.com": { + "domain": "westpalmweb.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "verdantloom.com": { - "domain": "verdantloom.com", + "whimsicalcanyon.com": { + "domain": "whimsicalcanyon.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "verseballs.com": { - "domain": "verseballs.com", + "whimsicalgrove.com": { + "domain": "whimsicalgrove.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "vibrantcelebration.com": { - "domain": "vibrantcelebration.com", + "whineattempt.com": { + "domain": "whineattempt.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "vibrantgale.com": { - "domain": "vibrantgale.com", + "whirlwealth.com": { + "domain": "whirlwealth.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "vibranthaven.com": { - "domain": "vibranthaven.com", + "whiskyqueue.com": { + "domain": "whiskyqueue.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "vibrantpact.com": { - "domain": "vibrantpact.com", + "whisperingcascade.com": { + "domain": "whisperingcascade.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "vibranttalisman.com": { - "domain": "vibranttalisman.com", + "whisperingcrib.com": { + "domain": "whisperingcrib.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "vibrantvale.com": { - "domain": "vibrantvale.com", + "whisperingquasar.com": { + "domain": "whisperingquasar.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "virtualvincent.com": { - "domain": "virtualvincent.com", + "whisperingsummit.com": { + "domain": "whisperingsummit.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "vividcanopy.com": { - "domain": "vividcanopy.com", + "whispermeeting.com": { + "domain": "whispermeeting.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "vividfrost.com": { - "domain": "vividfrost.com", + "wildcommittee.com": { + "domain": "wildcommittee.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "vividmeadow.com": { - "domain": "vividmeadow.com", + "wirecomic.com": { + "domain": "wirecomic.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "vividplume.com": { - "domain": "vividplume.com", + "wiredforcoffee.com": { + "domain": "wiredforcoffee.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "volatileprofit.com": { - "domain": "volatileprofit.com", + "wirypaste.com": { + "domain": "wirypaste.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "wantingwindow.com": { - "domain": "wantingwindow.com", + "wistfulwaste.com": { + "domain": "wistfulwaste.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "wearbasin.com": { - "domain": "wearbasin.com", + "wittypopcorn.com": { + "domain": "wittypopcorn.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "wellgroomedhydrant.com": { - "domain": "wellgroomedhydrant.com", + "wittyshack.com": { + "domain": "wittyshack.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "whimsicalcanyon.com": { - "domain": "whimsicalcanyon.com", + "workoperation.com": { + "domain": "workoperation.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "whimsicalgrove.com": { - "domain": "whimsicalgrove.com", + "worldlever.com": { + "domain": "worldlever.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "whisperingcascade.com": { - "domain": "whisperingcascade.com", + "worriednumber.com": { + "domain": "worriednumber.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "whisperingquasar.com": { - "domain": "whisperingquasar.com", + "worriedwine.com": { + "domain": "worriedwine.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "whisperingsummit.com": { - "domain": "whisperingsummit.com", + "wretchedfloor.com": { + "domain": "wretchedfloor.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "whispermeeting.com": { - "domain": "whispermeeting.com", + "wrongpotato.com": { + "domain": "wrongpotato.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "wildcommittee.com": { - "domain": "wildcommittee.com", + "wrongwound.com": { + "domain": "wrongwound.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "wistfulwaste.com": { - "domain": "wistfulwaste.com", + "wtaccesscontrol.com": { + "domain": "wtaccesscontrol.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "wittyshack.com": { - "domain": "wittyshack.com", + "xovq5nemr.com": { + "domain": "xovq5nemr.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "workoperation.com": { - "domain": "workoperation.com", + "yieldingwoman.com": { + "domain": "yieldingwoman.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "wretchedfloor.com": { - "domain": "wretchedfloor.com", + "zbwp6ghm.com": { + "domain": "zbwp6ghm.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" }, - "wrongwound.com": { - "domain": "wrongwound.com", + "zephyrcatalyst.com": { + "domain": "zephyrcatalyst.com", "owner": { "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -39873,7 +47342,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -39884,7 +47353,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -39895,7 +47364,18 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "zestywire.com": { + "domain": "zestywire.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -39906,7 +47386,7 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -39917,7 +47397,18 @@ "name": "Leven Labs, Inc. DBA Admiral", "displayName": "Admiral" }, - "prevalence": 0.0129, + "prevalence": 0.0109, + "fingerprinting": 1, + "cookies": 0.01, + "default": "block" + }, + "zonewedgeshaft.com": { + "domain": "zonewedgeshaft.com", + "owner": { + "name": "Leven Labs, Inc. DBA Admiral", + "displayName": "Admiral" + }, + "prevalence": 0.0109, "fingerprinting": 1, "cookies": 0.01, "default": "block" @@ -49929,61 +57420,105 @@ }, "Leven Labs, Inc. DBA Admiral": { "domains": [ + "2znp09oa.com", "4jnzhl0d0.com", + "5mcwl.pw", + "6ldu6qa.com", + "82o9v830.com", + "abilityscale.com", "aboardamusement.com", "aboardlevel.com", + "abovechat.com", + "abruptroad.com", "absentairport.com", "absorbingband.com", "absorbingcorn.com", + "absorbingprison.com", "abstractedamount.com", "abstractedauthority.com", + "absurdapple.com", + "abundantcoin.com", "acceptableauthority.com", "accurateanimal.com", "accuratecoal.com", + "achieverknee.com", + "acidicstraw.com", "acidpigs.com", + "acridangle.com", + "acridtwist.com", "actoramusement.com", + "actuallysheep.com", "actuallysnake.com", "actuallything.com", "adamantsnail.com", + "addictedattention.com", + "admiral.pub", "adorableanger.com", "adorableattention.com", "adventurousamount.com", + "afraidlanguage.com", + "aftermathbrother.com", "agilebreeze.com", "agreeablearch.com", "agreeabletouch.com", "aheadday.com", + "aheadgrow.com", + "aheadmachine.com", + "ak0gsh40.com", "alertarithmetic.com", "aliasanvil.com", "alikeaddition.com", "aliveachiever.com", + "alleythecat.com", "alluringbucket.com", + "aloofmetal.com", "aloofvest.com", + "alpineactor.com", "ambientdusk.com", "ambientlagoon.com", "ambiguousafternoon.com", + "ambiguousanger.com", "ambiguousdinosaurs.com", + "ambiguousincome.com", "ambrosialsummit.com", "amethystzenith.com", "amuckafternoon.com", "amusedbucket.com", + "analogwonder.com", "analyzecorona.com", "ancientact.com", "annoyedairport.com", "annoyingacoustics.com", "annoyingclover.com", + "anxiousapples.com", "aquaticowl.com", + "ar1nvz5.com", + "archswimming.com", + "aromamirror.com", "arrivegrowth.com", + "artthevoid.com", "aspiringapples.com", "aspiringattempt.com", + "aspiringtoy.com", "astonishingfood.com", + "astralhustle.com", + "astrallullaby.com", + "attendchase.com", "attractionbanana.com", + "attractivecap.com", "audioarctic.com", "automaticside.com", "automaticturkey.com", + "availablerest.com", + "avalonalbum.com", + "averageactivity.com", "awarealley.com", "awesomeagreement.com", "awzbijw.com", + "axiomaticalley.com", "axiomaticanger.com", + "azuremystique.com", + "backupcat.com", "badgeboat.com", "badgerabbit.com", "badgevolcano.com", @@ -49991,59 +57526,106 @@ "baitbaseball.com", "balloonbelieve.com", "ballsbanana.com", + "bananabarrel.com", "bandborder.com", "barbarousbase.com", + "basilfish.com", "basketballbelieve.com", + "baskettexture.com", "bawdybalance.com", + "bawdybeast.com", "beamvolcano.com", "beancontrol.com", + "bearmoonlodge.com", "bedsberry.com", + "beetleend.com", "beginnerpancake.com", "begintrain.com", + "berserkhydrant.com", + "bespokesandals.com", "bestboundary.com", + "bewilderedbattle.com", + "bewilderedblade.com", + "bhcumsc.com", + "bikepaws.com", "bikesboard.com", + "billowybead.com", "billowybelief.com", + "binspiredtees.com", "birthdaybelief.com", "blackbrake.com", "bleachbubble.com", + "bleachscarecrow.com", + "bleedlight.com", "blesspizzas.com", + "blissfulcrescendo.com", "blissfullagoon.com", + "blueeyedblow.com", "blushingbeast.com", "blushingbread.com", + "boatsvest.com", + "boilingbeetle.com", "boilingcredit.com", + "boostbehavior.com", "boredcrown.com", + "bouncyproperty.com", "boundarybusiness.com", + "boundlessargument.com", + "boundlessbrake.com", "boundlessveil.com", "brainybasin.com", "brainynut.com", "branchborder.com", + "brandsfive.com", + "brandybison.com", + "bravebone.com", "bravecalculator.com", "breadbalance.com", + "breakableinsurance.com", "breakfastboat.com", + "breezygrove.com", + "brianwould.com", "brighttoe.com", "briskstorm.com", "broadborder.com", + "broadboundary.com", + "broadcastbed.com", + "broaddoor.com", "brotherslocket.com", + "bruisebaseball.com", + "brunchforher.com", "buildingknife.com", "bulbbait.com", + "burgersalt.com", "burlywhistle.com", "burnbubble.com", "bushesbag.com", "bustlingbath.com", "bustlingbook.com", "butterbulb.com", + "butterburst.com", "buttonladybug.com", + "cakesdrum.com", "calculatingcircle.com", + "calculatingtoothbrush.com", "calculatorstatement.com", "callousbrake.com", "calmcactus.com", "calypsocapsule.com", + "cannonchange.com", + "capablecows.com", "capablecup.com", "capriciouscorn.com", "captivatingcanyon.com", + "captivatingillusion.com", + "captivatingpanorama.com", + "captivatingperformance.com", "carefuldolls.com", "caringcast.com", + "caringzinc.com", + "carloforward.com", "carpentercomparison.com", + "carscannon.com", "cartkitten.com", "carvecakes.com", "catalogcake.com", @@ -50052,62 +57634,108 @@ "causecherry.com", "cautiouscamera.com", "cautiouscherries.com", + "cautiouscrate.com", "cautiouscredit.com", "cavecurtain.com", "ceciliavenus.com", + "celestialeuphony.com", "celestialquasar.com", "celestialspectra.com", "chaireggnog.com", + "chairscrack.com", "chairsdonkey.com", "chalkoil.com", "changeablecats.com", + "channelcamp.com", "chargecracker.com", "charmingplate.com", + "charscroll.com", "cheerycraze.com", "cherriescare.com", + "chessbranch.com", "chesscolor.com", + "chesscrowd.com", "chickensstation.com", "childlikecrowd.com", "childlikeexample.com", "childlikeform.com", + "chilledliquid.com", + "chingovernment.com", "chinsnakes.com", "chipperisle.com", "chivalrouscord.com", + "chubbycreature.com", "chunkycactus.com", + "cicdserver.com", + "cinemabonus.com", "circlelevel.com", + "clammychicken.com", "cleanhaircut.com", "cloisteredcord.com", "cloisteredcurve.com", "closedcows.com", + "closefriction.com", + "cloudhustles.com", + "cloudjumbo.com", + "clovercabbage.com", + "clumsycar.com", "coatfood.com", "cobaltoverture.com", + "coffeesidehustle.com", "coldbalance.com", + "coldcreatives.com", + "colorfulafterthought.com", "colossalclouds.com", "colossalcoat.com", "colossalcry.com", "combativecar.com", + "combativedetail.com", "combbit.com", "combcattle.com", "combcompetition.com", + "cometquote.com", "comfortablecheese.com", + "comfygoodness.com", + "companyparcel.com", + "comparereaction.com", + "compiledoctor.com", "concernedchange.com", "concernedchickens.com", "condemnedcomb.com", + "conditionchange.com", "conditioncrush.com", "confesschairs.com", + "configchain.com", "confusedcart.com", + "connectashelf.com", + "consciouschairs.com", "consciouscheese.com", "consciousdirt.com", + "consumerzero.com", + "controlcola.com", + "controlhall.com", + "convertbatch.com", "cooingcoal.com", + "coordinatedbedroom.com", "coordinatedcoat.com", "copycarpenter.com", + "copyrightaccesscontrols.com", + "coralreverie.com", + "corgibeachday.com", "cosmicsculptor.com", + "cosmosjackson.com", "courageousbaby.com", "coverapparatus.com", + "coverlayer.com", + "cozydusk.com", "cozyhillside.com", "cozytryst.com", "crabbychin.com", + "crackedsafe.com", + "crafthenry.com", + "crashchance.com", "cratecamera.com", + "craterbox.com", "creatorcherry.com", "creatorpassenger.com", "creaturecabbage.com", @@ -50115,169 +57743,332 @@ "critictruck.com", "crookedcreature.com", "crowdedmass.com", + "cruisetourist.com", + "cryptvalue.com", "crystalboulevard.com", + "crystalstatus.com", "cubchannel.com", + "cubepins.com", + "cuddlycake.com", "cuddlylunchroom.com", + "culturedcamera.com", + "culturedfeather.com", + "cumbersomecar.com", "cumbersomecarpenter.com", + "cumbersomecloud.com", + "curiouschalk.com", + "curioussuccess.com", + "curlycannon.com", "currentcollar.com", + "curtaincows.com", "curvedhoney.com", + "curvycord.com", "curvycry.com", "cushiondrum.com", "cushionpig.com", + "cutcurrent.com", "cutechin.com", + "cyclopsdial.com", + "dailydivision.com", "damagedadvice.com", "damageddistance.com", "damdoor.com", "dampdock.com", + "dancemistake.com", "dandydune.com", "dandyglow.com", + "dapperdiscussion.com", "dapperfloor.com", + "datastoried.com", "daughterstone.com", + "daymodern.com", "dazzlingbook.com", + "deafeningdock.com", + "deafeningdowntown.com", "debonairdust.com", "debonairtree.com", + "debugentity.com", + "decidedrum.com", "decisivebase.com", "decisivedrawer.com", "decisiveducks.com", + "decoycreation.com", "deerbeginner.com", "defeatedbadge.com", + "defensevest.com", + "degreechariot.com", + "delegatediscussion.com", "delicatecascade.com", "deliciousducks.com", + "deltafault.com", + "deluxecrate.com", "dependenttrip.com", + "desirebucket.com", + "desiredirt.com", + "detailedgovernment.com", "detailedkitten.com", + "detectdinner.com", "detectdiscovery.com", + "detourgame.com", + "deviceseal.com", + "deviceworkshop.com", "devilishdinner.com", "dewdroplagoon.com", + "difficultfog.com", "digestiondrawer.com", "dinnerquartz.com", "diplomahawaii.com", + "direfuldesk.com", "disagreeabledrop.com", "discreetfield.com", "discreetquarter.com", + "distributionneck.com", + "distributionpocket.com", + "distributiontomatoes.com", + "disturbedquiet.com", + "divehope.com", "dk4ywix.com", "dockdigestion.com", + "dogsonclouds.com", "dollardelta.com", + "doubledefend.com", + "doubtdrawer.com", "dq95d35.com", "drainpaste.com", "dramaticdirection.com", "dreamycanyon.com", + "driftpizza.com", "drollwharf.com", + "drydrum.com", "dustydime.com", "dustyhammer.com", "eagereden.com", + "eagerflame.com", "eagerknight.com", + "earthyfarm.com", + "eatablesquare.com", + "echochief.com", "echoinghaven.com", "effervescentcoral.com", "effervescentvista.com", + "effulgentnook.com", "effulgenttempest.com", + "ejyymghi.com", "elasticchange.com", "elderlybean.com", + "elderlytown.com", + "elephantqueue.com", "elusivebreeze.com", + "elusivecascade.com", + "elysiantraverse.com", + "embellishedmeadow.com", + "embermosaic.com", + "emberwhisper.com", "eminentbubble.com", + "eminentend.com", + "emptyescort.com", + "enchantedskyline.com", "enchantingdiscovery.com", + "enchantingenchantment.com", "enchantingmystique.com", + "enchantingtundra.com", + "enchantingvalley.com", + "encourageshock.com", "encouragingthread.com", + "endlesstrust.com", "endurablebulb.com", + "energeticexample.com", "energeticladybug.com", + "engineergrape.com", "engineertrick.com", + "enigmaticblossom.com", "enigmaticcanyon.com", "enigmaticvoyage.com", "enormousearth.com", + "enormousfoot.com", + "enterdrama.com", "entertainskin.com", + "enthusiastictemper.com", "enviousshape.com", + "enviousthread.com", "equablekettle.com", + "etherealbamboo.com", "ethereallagoon.com", + "etherealpinnacle.com", + "etherealquasar.com", + "etherealripple.com", "evanescentedge.com", "evasivejar.com", "eventexistence.com", "exampleshake.com", "excitingtub.com", + "exclusivebrass.com", "executeknowledge.com", "exhibitsneeze.com", "expansioneggnog.com", "exquisiteartisanship.com", + "extractobservation.com", + "extralocker.com", + "extramonies.com", "exuberantedge.com", "facilitatebreakfast.com", + "fadechildren.com", "fadedsnow.com", "fadewaves.com", + "fairfeeling.com", "fairiesbranch.com", "fairytaleflame.com", "fallaciousfifth.com", + "falseframe.com", + "familiarrod.com", "fancyactivity.com", "fancydune.com", + "fancygrove.com", + "fangfeeling.com", + "fantastictone.com", + "farethief.com", "farmergoldfish.com", "farshake.com", "farsnails.com", "fastenfather.com", + "fasterfineart.com", + "fasterjson.com", "fatcoil.com", "faucetfoot.com", "faultycanvas.com", + "fearfulfish.com", "fearfulmint.com", "fearlessfaucet.com", + "fearlesstramp.com", "featherstage.com", + "feeblestamp.com", "feignedfaucet.com", + "fernwaycloud.com", "fertilefeeling.com", "fewjuice.com", "fewkittens.com", + "finalizeforce.com", "financefear.com", + "finestpiece.com", + "finitecube.com", + "firecatfilms.com", + "fireworkcamp.com", + "firstendpoint.com", "firstfrogs.com", + "firsttexture.com", + "fitmessage.com", + "fivesidedsquare.com", "fixedfold.com", + "flakyfeast.com", "flameuncle.com", "flimsycircle.com", "flimsythought.com", + "flippedfunnel.com", + "floodprincipal.com", "flourishingcollaboration.com", + "flourishingendeavor.com", "flourishinginnovation.com", "flourishingpartnership.com", + "flowersornament.com", "flowerstreatment.com", "flowerycreature.com", "floweryfact.com", "floweryflavor.com", + "floweryoperation.com", "flutteringfireman.com", + "foambench.com", "followborder.com", + "forecasttiger.com", + "foretellfifth.com", + "forevergears.com", + "forgetfulflowers.com", "forgetfulsnail.com", "fortunatemark.com", + "fractalcoast.com", "frailfruit.com", + "framebanana.com", "franticroof.com", + "frantictrail.com", + "frazzleart.com", + "freakyglass.com", "freezingbuilding.com", "frequentflesh.com", "friendlycrayon.com", + "friendlyfold.com", "friendwool.com", + "frightenedpotato.com", + "frogator.com", + "frogtray.com", "fronttoad.com", + "frugalfiestas.com", "fumblingform.com", + "functionalcrown.com", "functionalfeather.com", + "funoverbored.com", + "funoverflow.com", + "furnstudio.com", "furryfork.com", + "furryhorses.com", + "futuristicapparatus.com", + "futuristicfairies.com", "futuristicfifth.com", "futuristicframe.com", + "fuzzyaudio.com", "fuzzybasketball.com", "fuzzyerror.com", + "fvl1f.pw", "gammamaximum.com", + "gardenovens.com", "gaudyairplane.com", + "geekactive.com", + "generalprose.com", "generateoffice.com", "giantsvessel.com", "giddycoat.com", "giraffepiano.com", + "gitcrumbs.com", "givevacation.com", + "gladglen.com", "gladysway.com", + "glamhawk.com", "gleamingcow.com", + "gleaminghaven.com", "glisteningguide.com", + "glisteningsign.com", "glitteringbrook.com", "gloriousbeef.com", + "glowingmeadow.com", + "gluedpixel.com", "goldfishgrowth.com", "gondolagnome.com", + "goodbark.com", "gorgeousedge.com", "gracefulmilk.com", "grainmass.com", "grandfatherguitar.com", + "gravitygive.com", + "gravitykick.com", "grayoranges.com", "grayreceipt.com", "greasysquare.com", + "greyinstrument.com", + "gripcorn.com", + "groovyornament.com", + "grouchybrothers.com", "grouchypush.com", "grumpydime.com", + "grumpydrawer.com", "guardeddirection.com", + "guardedschool.com", + "guessdetail.com", "guidecent.com", + "guildalpha.com", "guiltlessbasketball.com", "gulliblegrip.com", + "gustocooking.com", "gustygrandmother.com", + "h78xb.pw", + "habitualhumor.com", "halcyoncanyon.com", "halcyonsculpture.com", "hallowedinvention.com", @@ -50285,64 +58076,122 @@ "haltingdivision.com", "haltinggold.com", "hammerhearing.com", + "handleteeth.com", + "handnorth.com", "handsomehose.com", + "handsomeindustry.com", "handsomelyhealth.com", "handsomelythumb.com", + "handsomeyam.com", "handyfield.com", "handyfireman.com", "handyincrease.com", "haplesshydrant.com", "haplessland.com", + "happysponge.com", "harborcaption.com", + "harborcub.com", + "harmonicbamboo.com", + "harmonywing.com", "hatefulrequest.com", "headydegree.com", + "headyhook.com", + "healflowers.com", + "hearinglizards.com", "heartbreakingmind.com", "hearthorn.com", + "heavydetail.com", "heavyplayground.com", "helpcollar.com", + "helpflame.com", + "hfc195b.com", + "highfalutinbox.com", "highfalutinhoney.com", + "hilariouszinc.com", "historicalbeam.com", "hocgeese.com", "hollowafterthought.com", + "homelycrown.com", "honeybulb.com", + "honeywhipped.com", + "honorablehydrant.com", "honorableland.com", "horsenectar.com", "hospitablehall.com", "hospitablehat.com", + "howdyinbox.com", + "humdrumhobbies.com", "humdrumtouch.com", + "hurtgrape.com", + "hypnoticwound.com", "hystericalcloth.com", + "hystericalfinger.com", + "i9w8p.pw", + "idolscene.com", "idyllicjazz.com", "illinvention.com", + "illustriousoatmeal.com", + "immensehoney.com", + "imminentshake.com", "importantmeat.com", + "importedincrease.com", + "importedinsect.com", + "importlocate.com", "impossibleexpansion.com", + "impossiblemove.com", "impulsejewel.com", "impulselumber.com", + "incomehippo.com", "incompetentjoke.com", "inconclusiveaction.com", + "infamousstream.com", + "innocentlamp.com", + "innocentwax.com", "inputicicle.com", "inquisitiveice.com", + "inquisitiveinvention.com", "intelligentscissors.com", + "intentlens.com", + "interestdust.com", "internalcondition.com", "internalsink.com", + "iotapool.com", "irritatingfog.com", + "itemslice.com", + "ivykiosk.com", "j93557g.com", + "jadeitite.com", + "jaderooster.com", + "jailbulb.com", + "joblessdrum.com", "jollylens.com", "joyfulkeen.com", + "joyoussurprise.com", "jubilantaura.com", "jubilantcanyon.com", "jubilantcascade.com", "jubilantglimmer.com", "jubilanttempest.com", "jubilantwhisper.com", + "justicejudo.com", + "k54nw.pw", "kaputquill.com", "keenquill.com", + "kindhush.com", + "kitesquirrel.com", "knitstamp.com", "knottyswing.com", + "laboredlight.com", "laboredlocket.com", "lameletters.com", + "lamplow.com", "largebrass.com", + "lasttaco.com", "laughablelizards.com", + "leaplunchroom.com", "leftliquid.com", + "lemonpackage.com", + "lemonsandjoy.com", "liftedknowledge.com", "lightenafterthought.com", "lighttalon.com", @@ -50357,28 +58206,50 @@ "looseloaf.com", "lorenzourban.com", "losslace.com", + "loudlunch.com", "lovelydrum.com", + "loveseashore.com", + "lp3tdqle.com", "ludicrousarch.com", + "lumberamount.com", "luminousboulevard.com", "luminouscatalyst.com", + "luminoussculptor.com", + "lumpygnome.com", "lumpylumber.com", "lunchroomlock.com", "lustroushaven.com", + "lyricshook.com", "maddeningpowder.com", + "madebyintent.com", "magicaljoin.com", + "magnetairport.com", + "majesticmountainrange.com", "majesticwaterscape.com", "majesticwilderness.com", "maliciousmusic.com", + "managedpush.com", + "mantrafox.com", + "marblediscussion.com", + "markahouse.com", + "markedmeasure.com", "marketspiders.com", "marriedbelief.com", + "marriedmailbox.com", "marriedvalue.com", + "massivemark.com", "materialisticmoon.com", + "materialmilk.com", "materialparcel.com", "materialplayground.com", "meadowlullaby.com", "measlymiddle.com", "meatydime.com", "meddleplant.com", + "mediatescarf.com", + "mediumshort.com", + "mellowhush.com", + "mellowmailbox.com", "melodiouschorus.com", "melodiouscomposition.com", "meltmilk.com", @@ -50390,23 +58261,37 @@ "merequartz.com", "merryopal.com", "merryvault.com", + "messagenovice.com", + "messyoranges.com", "mightyspiders.com", + "mimosamajor.com", + "mindfulgem.com", "minorcattle.com", + "minusmental.com", "minuteburst.com", + "miscreantmoon.com", + "mistyhorizon.com", + "mittencattle.com", "mixedreading.com", "modularmental.com", "monacobeatles.com", "moorshoes.com", "motionflowers.com", "motionlessbag.com", + "motionlessbelief.com", "motionlessmeeting.com", "movemeal.com", + "muddledaftermath.com", + "muddledmemory.com", "mundanenail.com", + "mundanepollution.com", "mushywaste.com", "muteknife.com", + "mutemailbox.com", "mysticalagoon.com", "naivestatement.com", "nappyattack.com", + "nappyneck.com", "neatshade.com", "nebulacrescent.com", "nebulajubilee.com", @@ -50415,93 +58300,171 @@ "nebulousquasar.com", "nebulousripple.com", "needlessnorth.com", + "needyneedle.com", + "neighborlywatch.com", "nervoussummer.com", + "niftygraphs.com", "niftyhospital.com", + "niftyjelly.com", "nightwound.com", + "nimbleplot.com", "nocturnalloom.com", + "nocturnalmystique.com", + "noiselessplough.com", + "nonchalantnerve.com", "nondescriptcrowd.com", "nondescriptnote.com", + "nondescriptstocking.com", + "nostalgicknot.com", "nostalgicneed.com", + "notifyglass.com", + "nudgeduck.com", + "nullnorth.com", "numberlessring.com", + "numerousnest.com", "nutritiousbean.com", "nuttyorganization.com", "oafishchance.com", + "oafishobservation.com", "obscenesidewalk.com", + "observantice.com", "oldfashionedoffer.com", + "omgthink.com", + "omniscientfeeling.com", + "onlywoofs.com", "opalquill.com", "operationchicken.com", + "operationnail.com", + "oppositeoperation.com", "optimallimit.com", "opulentsylvan.com", "orientedargument.com", + "orionember.com", + "ourblogthing.com", + "outgoinggiraffe.com", + "outsidevibe.com", "outstandingincome.com", "outstandingsnails.com", "overconfidentfood.com", + "overkick.com", + "overratedchalk.com", + "owlsr.us", + "oxygenfuse.com", + "pailcrime.com", "pailpatch.com", "painstakingpickle.com", + "paintpear.com", + "paleleaf.com", "pamelarandom.com", "panickycurtain.com", "panickypancake.com", "panoramicplane.com", "parallelbulb.com", "parchedsofa.com", + "pardonpopular.com", "parentpicture.com", + "parsimoniouspolice.com", "partplanes.com", "passivepolo.com", + "pastoralroad.com", + "pawsnug.com", "peacefullimit.com", + "pedromister.com", + "pedropanther.com", + "perceivequarter.com", + "perkyjade.com", "petiteumbrella.com", + "philippinch.com", + "photographpan.com", + "piespower.com", "piquantgrove.com", "piquantmeadow.com", + "piquantpigs.com", + "piquantprice.com", "piquantvortex.com", + "pixeledhub.com", + "pizzasnut.com", + "placeframe.com", "placidactivity.com", "placidperson.com", "planebasin.com", "plantdigestion.com", "playfulriver.com", "pleasantpump.com", + "plotparent.com", "plotrabbit.com", "pluckypocket.com", "pluckyzone.com", "pocketfaucet.com", "poeticpackage.com", "pointdigestion.com", + "pointlesshour.com", "pointlesspocket.com", "pointlessprofit.com", + "pointlessrifle.com", + "polarismagnet.com", "polishedcrescent.com", "polishedfolly.com", "politeplanes.com", + "politicalflip.com", "politicalporter.com", "popplantation.com", "possibleboats.com", "possiblepencil.com", "potatoinvention.com", "powderjourney.com", + "powerfulblends.com", "powerfulcopper.com", "preciousplanes.com", "predictplate.com", + "prefixpatriot.com", "prepareplanes.com", + "presetrabbits.com", + "previousplayground.com", + "previouspotato.com", "priceypies.com", "pricklydebt.com", "pricklypollution.com", "pristinegale.com", + "probablepartner.com", "processplantation.com", + "producepickle.com", + "productsurfer.com", + "profitrumour.com", "profusesupport.com", + "promiseair.com", + "proofconvert.com", + "propertypotato.com", "protestcopy.com", "psychedelicarithmetic.com", + "psychedelicchess.com", "publicsofa.com", + "puffyloss.com", + "puffypaste.com", + "puffypull.com", "puffypurpose.com", "pulsatingmeadow.com", "pumpedpancake.com", + "pumpedpurpose.com", "punyplant.com", + "puppytooth.com", "purposepipe.com", + "quacksquirrel.com", + "quaintcan.com", "quaintlake.com", + "quantumlagoon.com", + "quantumshine.com", + "queenskart.com", "quietknowledge.com", "quillkick.com", "quirkybliss.com", "quirkysugar.com", + "quixoticnebula.com", "quizzicalpartner.com", "quizzicalzephyr.com", "rabbitbreath.com", "rabbitrifle.com", + "radiantcanopy.com", "radiantlullaby.com", "radiateprose.com", "railwaygiraffe.com", @@ -50513,21 +58476,32 @@ "rangecake.com", "rangeplayground.com", "raresummer.com", + "reactjspdf.com", + "readingguilt.com", "readymoon.com", + "readysnails.com", + "realizedoor.com", + "realizerecess.com", + "rebelclover.com", "rebelhen.com", "rebelsubway.com", "rebelswing.com", + "receiptcent.com", + "receptiveink.com", "receptivereaction.com", "recessrain.com", "reconditeprison.com", "reconditerake.com", "reconditerespect.com", "reflectivestatement.com", + "refundradar.com", "regularplants.com", "regulatesleet.com", "rehabilitatereason.com", "relationrest.com", + "reloadphoto.com", "rememberdiscussion.com", + "rentinfinity.com", "repeatsweater.com", "replaceroute.com", "resonantbrush.com", @@ -50537,57 +58511,92 @@ "restrainstorm.com", "restructureinvention.com", "retrievemint.com", + "rhetoricalactivity.com", "rhetoricalloss.com", "rhetoricalveil.com", "rhymezebra.com", + "rhythmrule.com", "richstring.com", "righteouscrayon.com", "rightfulfall.com", "rigidrobin.com", "rigidveil.com", + "rigorlab.com", "ringplant.com", + "ringsrecord.com", + "ritzykey.com", + "ritzyrepresentative.com", + "ritzyveil.com", + "rockpebbles.com", "rollconnection.com", "roofrelation.com", "roseincome.com", + "rottenray.com", "ruralrobin.com", "rusticprice.com", + "ruthlessdegree.com", + "ruthlessmilk.com", + "sableloss.com", + "sablesmile.com", "sablesong.com", "sadloaf.com", + "saffronrefuge.com", + "sagargift.com", + "saltsacademy.com", "samesticks.com", "samestretch.com", "samplesamba.com", "satisfycork.com", "savoryorange.com", + "scarcecard.com", "scarceshock.com", + "scarcesign.com", "scarcestructure.com", + "scarcesurprise.com", "scaredcomfort.com", + "scaredsidewalk.com", "scaredslip.com", "scaredsnake.com", "scaredsnakes.com", "scaredsong.com", "scaredstomach.com", + "scaredswing.com", "scarefowl.com", "scarfsmash.com", + "scatteredheat.com", + "scatteredquiver.com", "scatteredstream.com", + "scenicapparel.com", "scientificshirt.com", "scintillatingscissors.com", "scintillatingsilver.com", "scissorsstatement.com", "scrapesleep.com", + "scratchsofa.com", "screechingfurniture.com", "screechingstocking.com", "screechingstove.com", "scribbleson.com", "scribblestring.com", + "scrollservice.com", + "scrubswim.com", "seashoresociety.com", "seatsmoke.com", "secondhandfall.com", + "secretivesheep.com", + "secretspiders.com", "secretturtle.com", + "seedscissors.com", "seemlysuggestion.com", "selectivesummer.com", + "selfishsea.com", "selfishsnake.com", + "sendingspire.com", + "sensorsmile.com", "separatesort.com", + "seraphichorizon.com", "seraphicjubilee.com", + "serendipityecho.com", "serenecascade.com", "serenepebble.com", "serenesurf.com", @@ -50595,23 +58604,32 @@ "serpentshampoo.com", "settleshoes.com", "shadeship.com", + "shaggytank.com", "shakegoldfish.com", "shakyseat.com", "shakysurprise.com", + "shakytaste.com", "shallowblade.com", "shamerain.com", "shapecomb.com", + "sharkskids.com", "sheargovernor.com", "shesubscriptions.com", "shinypond.com", "shirtsidewalk.com", "shiveringspot.com", "shiverscissors.com", + "shockinggrass.com", "shockingship.com", + "shredquiz.com", "shrillspoon.com", + "shydinosaurs.com", "sicksmash.com", "sierrakermit.com", + "signaturepod.com", + "siliconslow.com", "sillyscrew.com", + "simplesidewalk.com", "simulateswing.com", "sincerebuffalo.com", "sincerepelican.com", @@ -50620,69 +58638,124 @@ "sinkbooks.com", "sixauthority.com", "sixscissors.com", + "sizzlingsmoke.com", "skillfuldrop.com", "skisofa.com", + "slaysweater.com", + "slimyscarf.com", "slinksuggestion.com", "slopesoap.com", + "smallershops.com", "smashquartz.com", + "smashshoe.com", "smashsurprise.com", + "smilewound.com", + "smilingcattle.com", "smilingswim.com", + "smilingwaves.com", "smoggysnakes.com", "smoggysongs.com", + "smoggystation.com", + "snacktoken.com", + "snakemineral.com", + "snakeslang.com", "sneakwind.com", + "sneakystew.com", + "snoresmile.com", + "snowmentor.com", "soggysponge.com", "soggyzoo.com", "solarislabyrinth.com", "somberscarecrow.com", + "sombersea.com", + "sombersquirrel.com", "sombersticks.com", + "sombersurprise.com", "songsterritory.com", "soothingglade.com", + "sophisticatedstove.com", "sordidsmile.com", "soresidewalk.com", + "soresneeze.com", + "sorethunder.com", "soretrain.com", "sortsail.com", "sortsummer.com", "soundstocking.com", + "sowlettuce.com", + "spadelocket.com", + "sparkgoal.com", + "sparklingshelf.com", + "specialscissors.com", "spectacularstamp.com", "spellmist.com", "spellsalsa.com", + "spiffymachine.com", + "spirebaboon.com", "spookyexchange.com", "spookyskate.com", "spookysleet.com", + "spookystitch.com", + "spoonsilk.com", "spotlessstamp.com", "spottednoise.com", + "springolive.com", + "springsister.com", + "springsnails.com", + "sproutingbag.com", + "sprydelta.com", "sprysummit.com", "spuriousair.com", + "spuriousbase.com", + "spurioussquirrel.com", + "spuriousstranger.com", "spysubstance.com", "squalidscrew.com", + "squeakzinc.com", + "squealingturn.com", "stakingbasket.com", "stakingshock.com", "stakingsmile.com", + "staleshow.com", "stalesummer.com", + "starkscale.com", + "startingcars.com", + "statshunt.com", "statuesqueship.com", + "stayaction.com", "steadfastseat.com", "steadfastsound.com", "steadfastsystem.com", "steadycopper.com", "stealsteel.com", "steepscale.com", + "steepsister.com", "steepsquirrel.com", + "stepcattle.com", "stepplane.com", + "stepwisevideo.com", "stereoproxy.com", "stereotypedsugar.com", + "stewspiders.com", "stiffgame.com", + "stiffstem.com", "stimulatingsneeze.com", + "stingsquirrel.com", "stingycrush.com", "stingyshoe.com", "stingyspoon.com", "stockingsleet.com", + "stockingsneeze.com", "stomachscience.com", + "stonechin.com", "stopstomach.com", + "stormyachiever.com", "stormyfold.com", "straightnest.com", "strangeclocks.com", "strangersponge.com", "strangesink.com", + "streetsort.com", "stretchsister.com", "stretchsneeze.com", "stretchsquirrel.com", @@ -50693,85 +58766,149 @@ "stupendoussleet.com", "stupendoussnow.com", "stupidscene.com", + "sturdysnail.com", + "subletyoke.com", "sublimequartz.com", + "subsequentswim.com", + "substantialcarpenter.com", + "substantialgrade.com", "succeedscene.com", + "successfulscent.com", + "suddensoda.com", "sugarfriction.com", "suggestionbridge.com", "sulkycook.com", + "summerobject.com", + "sunshinegates.com", + "superchichair.com", "superficialeyes.com", "superficialspring.com", "superficialsquare.com", + "superviseshoes.com", "supportwaves.com", "suspectmark.com", "swankysquare.com", "swellstocking.com", "swelteringsleep.com", "swingslip.com", + "swordgoose.com", + "syllablesight.com", "synonymousrule.com", "synonymoussticks.com", "synthesizescarecrow.com", "tackytrains.com", + "tacojournal.com", + "talltouch.com", + "tangibleteam.com", "tangyamount.com", "tangycover.com", "tastelesstrees.com", "tastelesstrucks.com", + "tastesnake.com", + "tawdryson.com", + "tdzvm.pw", "tearfulglass.com", + "techconverter.com", + "tediousbear.com", "tediousticket.com", + "tedioustooth.com", "teenytinycellar.com", "teenytinyshirt.com", "teenytinytongue.com", + "telephoneapparatus.com", "tempertrick.com", + "tempttalk.com", "temptteam.com", "tendertest.com", "terriblethumb.com", "terrifictooth.com", + "testadmiral.com", + "texturetrick.com", + "therapeuticcars.com", + "thickticket.com", + "thicktrucks.com", + "thingsafterthought.com", "thingstaste.com", "thinkitten.com", + "thinkitwice.com", "thirdrespect.com", + "thirstytwig.com", "thomastorch.com", "thoughtlessknot.com", "threetruck.com", "thrivingmarketplace.com", "ticketaunt.com", + "ticklesign.com", "tidymitten.com", + "tightpowder.com", + "tinyswans.com", + "tinytendency.com", "tiredthroat.com", "tiresomethunder.com", + "toolcapital.com", + "toomanyalts.com", + "torpidtongue.com", + "trackcaddie.com", "tradetooth.com", + "trafficviews.com", + "tranquilamulet.com", + "tranquilarchipelago.com", "tranquilcan.com", "tranquilcanyon.com", "tranquilplume.com", + "tranquilside.com", "tranquilveil.com", "tranquilveranda.com", + "trappush.com", + "treadbun.com", "tremendousearthquake.com", "tremendousplastic.com", + "tremendoustime.com", "tritebadge.com", "tritethunder.com", + "tritetongue.com", "troubledtail.com", "troubleshade.com", + "truckstomatoes.com", "truculentrate.com", "tumbleicicle.com", + "tuneupcoffee.com", + "twistloss.com", + "twistsweater.com", "typicalairplane.com", "typicalteeth.com", + "tzwaw.pw", "ubiquitoussea.com", "ubiquitousyard.com", "ultraoranges.com", + "ultravalid.com", "unablehope.com", + "unaccountablecreator.com", "unaccountablepie.com", + "unarmedindustry.com", "unbecominghall.com", "unbecominglamp.com", "uncoveredexpert.com", + "understoodocean.com", "unequalbrake.com", "unequaltrail.com", "uninterestedquarter.com", + "unknowncontrol.com", "unknowncrate.com", + "unknowntray.com", + "untidyquestion.com", "untidyrice.com", "unusedstone.com", + "unusualtitle.com", "unwieldyhealth.com", "unwieldyimpulse.com", "unwieldyplastic.com", "uppitytime.com", "uselesslumber.com", + "validmemo.com", + "vanfireworks.com", "vanishmemory.com", + "velvetnova.com", "velvetquasar.com", "vengefulgrass.com", "venomousvessel.com", @@ -50779,46 +58916,81 @@ "verdantanswer.com", "verdantlabyrinth.com", "verdantloom.com", + "verdantsculpture.com", "verseballs.com", "vibrantcelebration.com", "vibrantgale.com", "vibranthaven.com", "vibrantpact.com", + "vibrantsundown.com", "vibranttalisman.com", "vibrantvale.com", + "victoriousrequest.com", "virtualvincent.com", "vividcanopy.com", "vividfrost.com", "vividmeadow.com", "vividplume.com", + "voicelessvein.com", + "voidgoo.com", "volatileprofit.com", "volatilevessel.com", "voraciousgrip.com", + "vq1qi.pw", + "waitingnumber.com", "wantingwindow.com", "warmafterthought.com", "warmquiver.com", + "warnwing.com", + "washbanana.com", + "wateryvan.com", + "waterywave.com", + "waterywrist.com", "wearbasin.com", + "websitesdude.com", + "wellgroomedapparel.com", "wellgroomedhydrant.com", + "wellmadefrog.com", + "westpalmweb.com", "whimsicalcanyon.com", "whimsicalgrove.com", + "whineattempt.com", + "whirlwealth.com", + "whiskyqueue.com", "whisperingcascade.com", + "whisperingcrib.com", "whisperingquasar.com", "whisperingsummit.com", "whispermeeting.com", "wildcommittee.com", + "wirecomic.com", + "wiredforcoffee.com", + "wirypaste.com", "wistfulwaste.com", + "wittypopcorn.com", "wittyshack.com", "workoperation.com", + "worldlever.com", + "worriednumber.com", + "worriedwine.com", "wretchedfloor.com", + "wrongpotato.com", "wrongwound.com", + "wtaccesscontrol.com", + "xovq5nemr.com", + "yieldingwoman.com", + "zbwp6ghm.com", + "zephyrcatalyst.com", "zephyrlabyrinth.com", "zestycrime.com", "zestyhorizon.com", "zestyrover.com", + "zestywire.com", "zipperxray.com", - "zlp6s.pw" + "zlp6s.pw", + "zonewedgeshaft.com" ], - "prevalence": 0.0129, + "prevalence": 0.0109, "displayName": "Admiral" } }, @@ -51533,61 +59705,105 @@ "zapposcouture.com": "Amazon Technologies, Inc.", "aamapi.com": "Alliance for Audited Media", "aamsitecertifier.com": "Alliance for Audited Media", + "2znp09oa.com": "Leven Labs, Inc. DBA Admiral", "4jnzhl0d0.com": "Leven Labs, Inc. DBA Admiral", + "5mcwl.pw": "Leven Labs, Inc. DBA Admiral", + "6ldu6qa.com": "Leven Labs, Inc. DBA Admiral", + "82o9v830.com": "Leven Labs, Inc. DBA Admiral", + "abilityscale.com": "Leven Labs, Inc. DBA Admiral", "aboardamusement.com": "Leven Labs, Inc. DBA Admiral", "aboardlevel.com": "Leven Labs, Inc. DBA Admiral", + "abovechat.com": "Leven Labs, Inc. DBA Admiral", + "abruptroad.com": "Leven Labs, Inc. DBA Admiral", "absentairport.com": "Leven Labs, Inc. DBA Admiral", "absorbingband.com": "Leven Labs, Inc. DBA Admiral", "absorbingcorn.com": "Leven Labs, Inc. DBA Admiral", + "absorbingprison.com": "Leven Labs, Inc. DBA Admiral", "abstractedamount.com": "Leven Labs, Inc. DBA Admiral", "abstractedauthority.com": "Leven Labs, Inc. DBA Admiral", + "absurdapple.com": "Leven Labs, Inc. DBA Admiral", + "abundantcoin.com": "Leven Labs, Inc. DBA Admiral", "acceptableauthority.com": "Leven Labs, Inc. DBA Admiral", "accurateanimal.com": "Leven Labs, Inc. DBA Admiral", "accuratecoal.com": "Leven Labs, Inc. DBA Admiral", + "achieverknee.com": "Leven Labs, Inc. DBA Admiral", + "acidicstraw.com": "Leven Labs, Inc. DBA Admiral", "acidpigs.com": "Leven Labs, Inc. DBA Admiral", + "acridangle.com": "Leven Labs, Inc. DBA Admiral", + "acridtwist.com": "Leven Labs, Inc. DBA Admiral", "actoramusement.com": "Leven Labs, Inc. DBA Admiral", + "actuallysheep.com": "Leven Labs, Inc. DBA Admiral", "actuallysnake.com": "Leven Labs, Inc. DBA Admiral", "actuallything.com": "Leven Labs, Inc. DBA Admiral", "adamantsnail.com": "Leven Labs, Inc. DBA Admiral", + "addictedattention.com": "Leven Labs, Inc. DBA Admiral", + "admiral.pub": "Leven Labs, Inc. DBA Admiral", "adorableanger.com": "Leven Labs, Inc. DBA Admiral", "adorableattention.com": "Leven Labs, Inc. DBA Admiral", "adventurousamount.com": "Leven Labs, Inc. DBA Admiral", + "afraidlanguage.com": "Leven Labs, Inc. DBA Admiral", + "aftermathbrother.com": "Leven Labs, Inc. DBA Admiral", "agilebreeze.com": "Leven Labs, Inc. DBA Admiral", "agreeablearch.com": "Leven Labs, Inc. DBA Admiral", "agreeabletouch.com": "Leven Labs, Inc. DBA Admiral", "aheadday.com": "Leven Labs, Inc. DBA Admiral", + "aheadgrow.com": "Leven Labs, Inc. DBA Admiral", + "aheadmachine.com": "Leven Labs, Inc. DBA Admiral", + "ak0gsh40.com": "Leven Labs, Inc. DBA Admiral", "alertarithmetic.com": "Leven Labs, Inc. DBA Admiral", "aliasanvil.com": "Leven Labs, Inc. DBA Admiral", "alikeaddition.com": "Leven Labs, Inc. DBA Admiral", "aliveachiever.com": "Leven Labs, Inc. DBA Admiral", + "alleythecat.com": "Leven Labs, Inc. DBA Admiral", "alluringbucket.com": "Leven Labs, Inc. DBA Admiral", + "aloofmetal.com": "Leven Labs, Inc. DBA Admiral", "aloofvest.com": "Leven Labs, Inc. DBA Admiral", + "alpineactor.com": "Leven Labs, Inc. DBA Admiral", "ambientdusk.com": "Leven Labs, Inc. DBA Admiral", "ambientlagoon.com": "Leven Labs, Inc. DBA Admiral", "ambiguousafternoon.com": "Leven Labs, Inc. DBA Admiral", + "ambiguousanger.com": "Leven Labs, Inc. DBA Admiral", "ambiguousdinosaurs.com": "Leven Labs, Inc. DBA Admiral", + "ambiguousincome.com": "Leven Labs, Inc. DBA Admiral", "ambrosialsummit.com": "Leven Labs, Inc. DBA Admiral", "amethystzenith.com": "Leven Labs, Inc. DBA Admiral", "amuckafternoon.com": "Leven Labs, Inc. DBA Admiral", "amusedbucket.com": "Leven Labs, Inc. DBA Admiral", + "analogwonder.com": "Leven Labs, Inc. DBA Admiral", "analyzecorona.com": "Leven Labs, Inc. DBA Admiral", "ancientact.com": "Leven Labs, Inc. DBA Admiral", "annoyedairport.com": "Leven Labs, Inc. DBA Admiral", "annoyingacoustics.com": "Leven Labs, Inc. DBA Admiral", "annoyingclover.com": "Leven Labs, Inc. DBA Admiral", + "anxiousapples.com": "Leven Labs, Inc. DBA Admiral", "aquaticowl.com": "Leven Labs, Inc. DBA Admiral", + "ar1nvz5.com": "Leven Labs, Inc. DBA Admiral", + "archswimming.com": "Leven Labs, Inc. DBA Admiral", + "aromamirror.com": "Leven Labs, Inc. DBA Admiral", "arrivegrowth.com": "Leven Labs, Inc. DBA Admiral", + "artthevoid.com": "Leven Labs, Inc. DBA Admiral", "aspiringapples.com": "Leven Labs, Inc. DBA Admiral", "aspiringattempt.com": "Leven Labs, Inc. DBA Admiral", + "aspiringtoy.com": "Leven Labs, Inc. DBA Admiral", "astonishingfood.com": "Leven Labs, Inc. DBA Admiral", + "astralhustle.com": "Leven Labs, Inc. DBA Admiral", + "astrallullaby.com": "Leven Labs, Inc. DBA Admiral", + "attendchase.com": "Leven Labs, Inc. DBA Admiral", "attractionbanana.com": "Leven Labs, Inc. DBA Admiral", + "attractivecap.com": "Leven Labs, Inc. DBA Admiral", "audioarctic.com": "Leven Labs, Inc. DBA Admiral", "automaticside.com": "Leven Labs, Inc. DBA Admiral", "automaticturkey.com": "Leven Labs, Inc. DBA Admiral", + "availablerest.com": "Leven Labs, Inc. DBA Admiral", + "avalonalbum.com": "Leven Labs, Inc. DBA Admiral", + "averageactivity.com": "Leven Labs, Inc. DBA Admiral", "awarealley.com": "Leven Labs, Inc. DBA Admiral", "awesomeagreement.com": "Leven Labs, Inc. DBA Admiral", "awzbijw.com": "Leven Labs, Inc. DBA Admiral", + "axiomaticalley.com": "Leven Labs, Inc. DBA Admiral", "axiomaticanger.com": "Leven Labs, Inc. DBA Admiral", + "azuremystique.com": "Leven Labs, Inc. DBA Admiral", + "backupcat.com": "Leven Labs, Inc. DBA Admiral", "badgeboat.com": "Leven Labs, Inc. DBA Admiral", "badgerabbit.com": "Leven Labs, Inc. DBA Admiral", "badgevolcano.com": "Leven Labs, Inc. DBA Admiral", @@ -51595,59 +59811,106 @@ "baitbaseball.com": "Leven Labs, Inc. DBA Admiral", "balloonbelieve.com": "Leven Labs, Inc. DBA Admiral", "ballsbanana.com": "Leven Labs, Inc. DBA Admiral", + "bananabarrel.com": "Leven Labs, Inc. DBA Admiral", "bandborder.com": "Leven Labs, Inc. DBA Admiral", "barbarousbase.com": "Leven Labs, Inc. DBA Admiral", + "basilfish.com": "Leven Labs, Inc. DBA Admiral", "basketballbelieve.com": "Leven Labs, Inc. DBA Admiral", + "baskettexture.com": "Leven Labs, Inc. DBA Admiral", "bawdybalance.com": "Leven Labs, Inc. DBA Admiral", + "bawdybeast.com": "Leven Labs, Inc. DBA Admiral", "beamvolcano.com": "Leven Labs, Inc. DBA Admiral", "beancontrol.com": "Leven Labs, Inc. DBA Admiral", + "bearmoonlodge.com": "Leven Labs, Inc. DBA Admiral", "bedsberry.com": "Leven Labs, Inc. DBA Admiral", + "beetleend.com": "Leven Labs, Inc. DBA Admiral", "beginnerpancake.com": "Leven Labs, Inc. DBA Admiral", "begintrain.com": "Leven Labs, Inc. DBA Admiral", + "berserkhydrant.com": "Leven Labs, Inc. DBA Admiral", + "bespokesandals.com": "Leven Labs, Inc. DBA Admiral", "bestboundary.com": "Leven Labs, Inc. DBA Admiral", + "bewilderedbattle.com": "Leven Labs, Inc. DBA Admiral", + "bewilderedblade.com": "Leven Labs, Inc. DBA Admiral", + "bhcumsc.com": "Leven Labs, Inc. DBA Admiral", + "bikepaws.com": "Leven Labs, Inc. DBA Admiral", "bikesboard.com": "Leven Labs, Inc. DBA Admiral", + "billowybead.com": "Leven Labs, Inc. DBA Admiral", "billowybelief.com": "Leven Labs, Inc. DBA Admiral", + "binspiredtees.com": "Leven Labs, Inc. DBA Admiral", "birthdaybelief.com": "Leven Labs, Inc. DBA Admiral", "blackbrake.com": "Leven Labs, Inc. DBA Admiral", "bleachbubble.com": "Leven Labs, Inc. DBA Admiral", + "bleachscarecrow.com": "Leven Labs, Inc. DBA Admiral", + "bleedlight.com": "Leven Labs, Inc. DBA Admiral", "blesspizzas.com": "Leven Labs, Inc. DBA Admiral", + "blissfulcrescendo.com": "Leven Labs, Inc. DBA Admiral", "blissfullagoon.com": "Leven Labs, Inc. DBA Admiral", + "blueeyedblow.com": "Leven Labs, Inc. DBA Admiral", "blushingbeast.com": "Leven Labs, Inc. DBA Admiral", "blushingbread.com": "Leven Labs, Inc. DBA Admiral", + "boatsvest.com": "Leven Labs, Inc. DBA Admiral", + "boilingbeetle.com": "Leven Labs, Inc. DBA Admiral", "boilingcredit.com": "Leven Labs, Inc. DBA Admiral", + "boostbehavior.com": "Leven Labs, Inc. DBA Admiral", "boredcrown.com": "Leven Labs, Inc. DBA Admiral", + "bouncyproperty.com": "Leven Labs, Inc. DBA Admiral", "boundarybusiness.com": "Leven Labs, Inc. DBA Admiral", + "boundlessargument.com": "Leven Labs, Inc. DBA Admiral", + "boundlessbrake.com": "Leven Labs, Inc. DBA Admiral", "boundlessveil.com": "Leven Labs, Inc. DBA Admiral", "brainybasin.com": "Leven Labs, Inc. DBA Admiral", "brainynut.com": "Leven Labs, Inc. DBA Admiral", "branchborder.com": "Leven Labs, Inc. DBA Admiral", + "brandsfive.com": "Leven Labs, Inc. DBA Admiral", + "brandybison.com": "Leven Labs, Inc. DBA Admiral", + "bravebone.com": "Leven Labs, Inc. DBA Admiral", "bravecalculator.com": "Leven Labs, Inc. DBA Admiral", "breadbalance.com": "Leven Labs, Inc. DBA Admiral", + "breakableinsurance.com": "Leven Labs, Inc. DBA Admiral", "breakfastboat.com": "Leven Labs, Inc. DBA Admiral", + "breezygrove.com": "Leven Labs, Inc. DBA Admiral", + "brianwould.com": "Leven Labs, Inc. DBA Admiral", "brighttoe.com": "Leven Labs, Inc. DBA Admiral", "briskstorm.com": "Leven Labs, Inc. DBA Admiral", "broadborder.com": "Leven Labs, Inc. DBA Admiral", + "broadboundary.com": "Leven Labs, Inc. DBA Admiral", + "broadcastbed.com": "Leven Labs, Inc. DBA Admiral", + "broaddoor.com": "Leven Labs, Inc. DBA Admiral", "brotherslocket.com": "Leven Labs, Inc. DBA Admiral", + "bruisebaseball.com": "Leven Labs, Inc. DBA Admiral", + "brunchforher.com": "Leven Labs, Inc. DBA Admiral", "buildingknife.com": "Leven Labs, Inc. DBA Admiral", "bulbbait.com": "Leven Labs, Inc. DBA Admiral", + "burgersalt.com": "Leven Labs, Inc. DBA Admiral", "burlywhistle.com": "Leven Labs, Inc. DBA Admiral", "burnbubble.com": "Leven Labs, Inc. DBA Admiral", "bushesbag.com": "Leven Labs, Inc. DBA Admiral", "bustlingbath.com": "Leven Labs, Inc. DBA Admiral", "bustlingbook.com": "Leven Labs, Inc. DBA Admiral", "butterbulb.com": "Leven Labs, Inc. DBA Admiral", + "butterburst.com": "Leven Labs, Inc. DBA Admiral", "buttonladybug.com": "Leven Labs, Inc. DBA Admiral", + "cakesdrum.com": "Leven Labs, Inc. DBA Admiral", "calculatingcircle.com": "Leven Labs, Inc. DBA Admiral", + "calculatingtoothbrush.com": "Leven Labs, Inc. DBA Admiral", "calculatorstatement.com": "Leven Labs, Inc. DBA Admiral", "callousbrake.com": "Leven Labs, Inc. DBA Admiral", "calmcactus.com": "Leven Labs, Inc. DBA Admiral", "calypsocapsule.com": "Leven Labs, Inc. DBA Admiral", + "cannonchange.com": "Leven Labs, Inc. DBA Admiral", + "capablecows.com": "Leven Labs, Inc. DBA Admiral", "capablecup.com": "Leven Labs, Inc. DBA Admiral", "capriciouscorn.com": "Leven Labs, Inc. DBA Admiral", "captivatingcanyon.com": "Leven Labs, Inc. DBA Admiral", + "captivatingillusion.com": "Leven Labs, Inc. DBA Admiral", + "captivatingpanorama.com": "Leven Labs, Inc. DBA Admiral", + "captivatingperformance.com": "Leven Labs, Inc. DBA Admiral", "carefuldolls.com": "Leven Labs, Inc. DBA Admiral", "caringcast.com": "Leven Labs, Inc. DBA Admiral", + "caringzinc.com": "Leven Labs, Inc. DBA Admiral", + "carloforward.com": "Leven Labs, Inc. DBA Admiral", "carpentercomparison.com": "Leven Labs, Inc. DBA Admiral", + "carscannon.com": "Leven Labs, Inc. DBA Admiral", "cartkitten.com": "Leven Labs, Inc. DBA Admiral", "carvecakes.com": "Leven Labs, Inc. DBA Admiral", "catalogcake.com": "Leven Labs, Inc. DBA Admiral", @@ -51656,62 +59919,108 @@ "causecherry.com": "Leven Labs, Inc. DBA Admiral", "cautiouscamera.com": "Leven Labs, Inc. DBA Admiral", "cautiouscherries.com": "Leven Labs, Inc. DBA Admiral", + "cautiouscrate.com": "Leven Labs, Inc. DBA Admiral", "cautiouscredit.com": "Leven Labs, Inc. DBA Admiral", "cavecurtain.com": "Leven Labs, Inc. DBA Admiral", "ceciliavenus.com": "Leven Labs, Inc. DBA Admiral", + "celestialeuphony.com": "Leven Labs, Inc. DBA Admiral", "celestialquasar.com": "Leven Labs, Inc. DBA Admiral", "celestialspectra.com": "Leven Labs, Inc. DBA Admiral", "chaireggnog.com": "Leven Labs, Inc. DBA Admiral", + "chairscrack.com": "Leven Labs, Inc. DBA Admiral", "chairsdonkey.com": "Leven Labs, Inc. DBA Admiral", "chalkoil.com": "Leven Labs, Inc. DBA Admiral", "changeablecats.com": "Leven Labs, Inc. DBA Admiral", + "channelcamp.com": "Leven Labs, Inc. DBA Admiral", "chargecracker.com": "Leven Labs, Inc. DBA Admiral", "charmingplate.com": "Leven Labs, Inc. DBA Admiral", + "charscroll.com": "Leven Labs, Inc. DBA Admiral", "cheerycraze.com": "Leven Labs, Inc. DBA Admiral", "cherriescare.com": "Leven Labs, Inc. DBA Admiral", + "chessbranch.com": "Leven Labs, Inc. DBA Admiral", "chesscolor.com": "Leven Labs, Inc. DBA Admiral", + "chesscrowd.com": "Leven Labs, Inc. DBA Admiral", "chickensstation.com": "Leven Labs, Inc. DBA Admiral", "childlikecrowd.com": "Leven Labs, Inc. DBA Admiral", "childlikeexample.com": "Leven Labs, Inc. DBA Admiral", "childlikeform.com": "Leven Labs, Inc. DBA Admiral", + "chilledliquid.com": "Leven Labs, Inc. DBA Admiral", + "chingovernment.com": "Leven Labs, Inc. DBA Admiral", "chinsnakes.com": "Leven Labs, Inc. DBA Admiral", "chipperisle.com": "Leven Labs, Inc. DBA Admiral", "chivalrouscord.com": "Leven Labs, Inc. DBA Admiral", + "chubbycreature.com": "Leven Labs, Inc. DBA Admiral", "chunkycactus.com": "Leven Labs, Inc. DBA Admiral", + "cicdserver.com": "Leven Labs, Inc. DBA Admiral", + "cinemabonus.com": "Leven Labs, Inc. DBA Admiral", "circlelevel.com": "Leven Labs, Inc. DBA Admiral", + "clammychicken.com": "Leven Labs, Inc. DBA Admiral", "cleanhaircut.com": "Leven Labs, Inc. DBA Admiral", "cloisteredcord.com": "Leven Labs, Inc. DBA Admiral", "cloisteredcurve.com": "Leven Labs, Inc. DBA Admiral", "closedcows.com": "Leven Labs, Inc. DBA Admiral", + "closefriction.com": "Leven Labs, Inc. DBA Admiral", + "cloudhustles.com": "Leven Labs, Inc. DBA Admiral", + "cloudjumbo.com": "Leven Labs, Inc. DBA Admiral", + "clovercabbage.com": "Leven Labs, Inc. DBA Admiral", + "clumsycar.com": "Leven Labs, Inc. DBA Admiral", "coatfood.com": "Leven Labs, Inc. DBA Admiral", "cobaltoverture.com": "Leven Labs, Inc. DBA Admiral", + "coffeesidehustle.com": "Leven Labs, Inc. DBA Admiral", "coldbalance.com": "Leven Labs, Inc. DBA Admiral", + "coldcreatives.com": "Leven Labs, Inc. DBA Admiral", + "colorfulafterthought.com": "Leven Labs, Inc. DBA Admiral", "colossalclouds.com": "Leven Labs, Inc. DBA Admiral", "colossalcoat.com": "Leven Labs, Inc. DBA Admiral", "colossalcry.com": "Leven Labs, Inc. DBA Admiral", "combativecar.com": "Leven Labs, Inc. DBA Admiral", + "combativedetail.com": "Leven Labs, Inc. DBA Admiral", "combbit.com": "Leven Labs, Inc. DBA Admiral", "combcattle.com": "Leven Labs, Inc. DBA Admiral", "combcompetition.com": "Leven Labs, Inc. DBA Admiral", + "cometquote.com": "Leven Labs, Inc. DBA Admiral", "comfortablecheese.com": "Leven Labs, Inc. DBA Admiral", + "comfygoodness.com": "Leven Labs, Inc. DBA Admiral", + "companyparcel.com": "Leven Labs, Inc. DBA Admiral", + "comparereaction.com": "Leven Labs, Inc. DBA Admiral", + "compiledoctor.com": "Leven Labs, Inc. DBA Admiral", "concernedchange.com": "Leven Labs, Inc. DBA Admiral", "concernedchickens.com": "Leven Labs, Inc. DBA Admiral", "condemnedcomb.com": "Leven Labs, Inc. DBA Admiral", + "conditionchange.com": "Leven Labs, Inc. DBA Admiral", "conditioncrush.com": "Leven Labs, Inc. DBA Admiral", "confesschairs.com": "Leven Labs, Inc. DBA Admiral", + "configchain.com": "Leven Labs, Inc. DBA Admiral", "confusedcart.com": "Leven Labs, Inc. DBA Admiral", + "connectashelf.com": "Leven Labs, Inc. DBA Admiral", + "consciouschairs.com": "Leven Labs, Inc. DBA Admiral", "consciouscheese.com": "Leven Labs, Inc. DBA Admiral", "consciousdirt.com": "Leven Labs, Inc. DBA Admiral", + "consumerzero.com": "Leven Labs, Inc. DBA Admiral", + "controlcola.com": "Leven Labs, Inc. DBA Admiral", + "controlhall.com": "Leven Labs, Inc. DBA Admiral", + "convertbatch.com": "Leven Labs, Inc. DBA Admiral", "cooingcoal.com": "Leven Labs, Inc. DBA Admiral", + "coordinatedbedroom.com": "Leven Labs, Inc. DBA Admiral", "coordinatedcoat.com": "Leven Labs, Inc. DBA Admiral", "copycarpenter.com": "Leven Labs, Inc. DBA Admiral", + "copyrightaccesscontrols.com": "Leven Labs, Inc. DBA Admiral", + "coralreverie.com": "Leven Labs, Inc. DBA Admiral", + "corgibeachday.com": "Leven Labs, Inc. DBA Admiral", "cosmicsculptor.com": "Leven Labs, Inc. DBA Admiral", + "cosmosjackson.com": "Leven Labs, Inc. DBA Admiral", "courageousbaby.com": "Leven Labs, Inc. DBA Admiral", "coverapparatus.com": "Leven Labs, Inc. DBA Admiral", + "coverlayer.com": "Leven Labs, Inc. DBA Admiral", + "cozydusk.com": "Leven Labs, Inc. DBA Admiral", "cozyhillside.com": "Leven Labs, Inc. DBA Admiral", "cozytryst.com": "Leven Labs, Inc. DBA Admiral", "crabbychin.com": "Leven Labs, Inc. DBA Admiral", + "crackedsafe.com": "Leven Labs, Inc. DBA Admiral", + "crafthenry.com": "Leven Labs, Inc. DBA Admiral", + "crashchance.com": "Leven Labs, Inc. DBA Admiral", "cratecamera.com": "Leven Labs, Inc. DBA Admiral", + "craterbox.com": "Leven Labs, Inc. DBA Admiral", "creatorcherry.com": "Leven Labs, Inc. DBA Admiral", "creatorpassenger.com": "Leven Labs, Inc. DBA Admiral", "creaturecabbage.com": "Leven Labs, Inc. DBA Admiral", @@ -51719,169 +60028,332 @@ "critictruck.com": "Leven Labs, Inc. DBA Admiral", "crookedcreature.com": "Leven Labs, Inc. DBA Admiral", "crowdedmass.com": "Leven Labs, Inc. DBA Admiral", + "cruisetourist.com": "Leven Labs, Inc. DBA Admiral", + "cryptvalue.com": "Leven Labs, Inc. DBA Admiral", "crystalboulevard.com": "Leven Labs, Inc. DBA Admiral", + "crystalstatus.com": "Leven Labs, Inc. DBA Admiral", "cubchannel.com": "Leven Labs, Inc. DBA Admiral", + "cubepins.com": "Leven Labs, Inc. DBA Admiral", + "cuddlycake.com": "Leven Labs, Inc. DBA Admiral", "cuddlylunchroom.com": "Leven Labs, Inc. DBA Admiral", + "culturedcamera.com": "Leven Labs, Inc. DBA Admiral", + "culturedfeather.com": "Leven Labs, Inc. DBA Admiral", + "cumbersomecar.com": "Leven Labs, Inc. DBA Admiral", "cumbersomecarpenter.com": "Leven Labs, Inc. DBA Admiral", + "cumbersomecloud.com": "Leven Labs, Inc. DBA Admiral", + "curiouschalk.com": "Leven Labs, Inc. DBA Admiral", + "curioussuccess.com": "Leven Labs, Inc. DBA Admiral", + "curlycannon.com": "Leven Labs, Inc. DBA Admiral", "currentcollar.com": "Leven Labs, Inc. DBA Admiral", + "curtaincows.com": "Leven Labs, Inc. DBA Admiral", "curvedhoney.com": "Leven Labs, Inc. DBA Admiral", + "curvycord.com": "Leven Labs, Inc. DBA Admiral", "curvycry.com": "Leven Labs, Inc. DBA Admiral", "cushiondrum.com": "Leven Labs, Inc. DBA Admiral", "cushionpig.com": "Leven Labs, Inc. DBA Admiral", + "cutcurrent.com": "Leven Labs, Inc. DBA Admiral", "cutechin.com": "Leven Labs, Inc. DBA Admiral", + "cyclopsdial.com": "Leven Labs, Inc. DBA Admiral", + "dailydivision.com": "Leven Labs, Inc. DBA Admiral", "damagedadvice.com": "Leven Labs, Inc. DBA Admiral", "damageddistance.com": "Leven Labs, Inc. DBA Admiral", "damdoor.com": "Leven Labs, Inc. DBA Admiral", "dampdock.com": "Leven Labs, Inc. DBA Admiral", + "dancemistake.com": "Leven Labs, Inc. DBA Admiral", "dandydune.com": "Leven Labs, Inc. DBA Admiral", "dandyglow.com": "Leven Labs, Inc. DBA Admiral", + "dapperdiscussion.com": "Leven Labs, Inc. DBA Admiral", "dapperfloor.com": "Leven Labs, Inc. DBA Admiral", + "datastoried.com": "Leven Labs, Inc. DBA Admiral", "daughterstone.com": "Leven Labs, Inc. DBA Admiral", + "daymodern.com": "Leven Labs, Inc. DBA Admiral", "dazzlingbook.com": "Leven Labs, Inc. DBA Admiral", + "deafeningdock.com": "Leven Labs, Inc. DBA Admiral", + "deafeningdowntown.com": "Leven Labs, Inc. DBA Admiral", "debonairdust.com": "Leven Labs, Inc. DBA Admiral", "debonairtree.com": "Leven Labs, Inc. DBA Admiral", + "debugentity.com": "Leven Labs, Inc. DBA Admiral", + "decidedrum.com": "Leven Labs, Inc. DBA Admiral", "decisivebase.com": "Leven Labs, Inc. DBA Admiral", "decisivedrawer.com": "Leven Labs, Inc. DBA Admiral", "decisiveducks.com": "Leven Labs, Inc. DBA Admiral", + "decoycreation.com": "Leven Labs, Inc. DBA Admiral", "deerbeginner.com": "Leven Labs, Inc. DBA Admiral", "defeatedbadge.com": "Leven Labs, Inc. DBA Admiral", + "defensevest.com": "Leven Labs, Inc. DBA Admiral", + "degreechariot.com": "Leven Labs, Inc. DBA Admiral", + "delegatediscussion.com": "Leven Labs, Inc. DBA Admiral", "delicatecascade.com": "Leven Labs, Inc. DBA Admiral", "deliciousducks.com": "Leven Labs, Inc. DBA Admiral", + "deltafault.com": "Leven Labs, Inc. DBA Admiral", + "deluxecrate.com": "Leven Labs, Inc. DBA Admiral", "dependenttrip.com": "Leven Labs, Inc. DBA Admiral", + "desirebucket.com": "Leven Labs, Inc. DBA Admiral", + "desiredirt.com": "Leven Labs, Inc. DBA Admiral", + "detailedgovernment.com": "Leven Labs, Inc. DBA Admiral", "detailedkitten.com": "Leven Labs, Inc. DBA Admiral", + "detectdinner.com": "Leven Labs, Inc. DBA Admiral", "detectdiscovery.com": "Leven Labs, Inc. DBA Admiral", + "detourgame.com": "Leven Labs, Inc. DBA Admiral", + "deviceseal.com": "Leven Labs, Inc. DBA Admiral", + "deviceworkshop.com": "Leven Labs, Inc. DBA Admiral", "devilishdinner.com": "Leven Labs, Inc. DBA Admiral", "dewdroplagoon.com": "Leven Labs, Inc. DBA Admiral", + "difficultfog.com": "Leven Labs, Inc. DBA Admiral", "digestiondrawer.com": "Leven Labs, Inc. DBA Admiral", "dinnerquartz.com": "Leven Labs, Inc. DBA Admiral", "diplomahawaii.com": "Leven Labs, Inc. DBA Admiral", + "direfuldesk.com": "Leven Labs, Inc. DBA Admiral", "disagreeabledrop.com": "Leven Labs, Inc. DBA Admiral", "discreetfield.com": "Leven Labs, Inc. DBA Admiral", "discreetquarter.com": "Leven Labs, Inc. DBA Admiral", + "distributionneck.com": "Leven Labs, Inc. DBA Admiral", + "distributionpocket.com": "Leven Labs, Inc. DBA Admiral", + "distributiontomatoes.com": "Leven Labs, Inc. DBA Admiral", + "disturbedquiet.com": "Leven Labs, Inc. DBA Admiral", + "divehope.com": "Leven Labs, Inc. DBA Admiral", "dk4ywix.com": "Leven Labs, Inc. DBA Admiral", "dockdigestion.com": "Leven Labs, Inc. DBA Admiral", + "dogsonclouds.com": "Leven Labs, Inc. DBA Admiral", "dollardelta.com": "Leven Labs, Inc. DBA Admiral", + "doubledefend.com": "Leven Labs, Inc. DBA Admiral", + "doubtdrawer.com": "Leven Labs, Inc. DBA Admiral", "dq95d35.com": "Leven Labs, Inc. DBA Admiral", "drainpaste.com": "Leven Labs, Inc. DBA Admiral", "dramaticdirection.com": "Leven Labs, Inc. DBA Admiral", "dreamycanyon.com": "Leven Labs, Inc. DBA Admiral", + "driftpizza.com": "Leven Labs, Inc. DBA Admiral", "drollwharf.com": "Leven Labs, Inc. DBA Admiral", + "drydrum.com": "Leven Labs, Inc. DBA Admiral", "dustydime.com": "Leven Labs, Inc. DBA Admiral", "dustyhammer.com": "Leven Labs, Inc. DBA Admiral", "eagereden.com": "Leven Labs, Inc. DBA Admiral", + "eagerflame.com": "Leven Labs, Inc. DBA Admiral", "eagerknight.com": "Leven Labs, Inc. DBA Admiral", + "earthyfarm.com": "Leven Labs, Inc. DBA Admiral", + "eatablesquare.com": "Leven Labs, Inc. DBA Admiral", + "echochief.com": "Leven Labs, Inc. DBA Admiral", "echoinghaven.com": "Leven Labs, Inc. DBA Admiral", "effervescentcoral.com": "Leven Labs, Inc. DBA Admiral", "effervescentvista.com": "Leven Labs, Inc. DBA Admiral", + "effulgentnook.com": "Leven Labs, Inc. DBA Admiral", "effulgenttempest.com": "Leven Labs, Inc. DBA Admiral", + "ejyymghi.com": "Leven Labs, Inc. DBA Admiral", "elasticchange.com": "Leven Labs, Inc. DBA Admiral", "elderlybean.com": "Leven Labs, Inc. DBA Admiral", + "elderlytown.com": "Leven Labs, Inc. DBA Admiral", + "elephantqueue.com": "Leven Labs, Inc. DBA Admiral", "elusivebreeze.com": "Leven Labs, Inc. DBA Admiral", + "elusivecascade.com": "Leven Labs, Inc. DBA Admiral", + "elysiantraverse.com": "Leven Labs, Inc. DBA Admiral", + "embellishedmeadow.com": "Leven Labs, Inc. DBA Admiral", + "embermosaic.com": "Leven Labs, Inc. DBA Admiral", + "emberwhisper.com": "Leven Labs, Inc. DBA Admiral", "eminentbubble.com": "Leven Labs, Inc. DBA Admiral", + "eminentend.com": "Leven Labs, Inc. DBA Admiral", + "emptyescort.com": "Leven Labs, Inc. DBA Admiral", + "enchantedskyline.com": "Leven Labs, Inc. DBA Admiral", "enchantingdiscovery.com": "Leven Labs, Inc. DBA Admiral", + "enchantingenchantment.com": "Leven Labs, Inc. DBA Admiral", "enchantingmystique.com": "Leven Labs, Inc. DBA Admiral", + "enchantingtundra.com": "Leven Labs, Inc. DBA Admiral", + "enchantingvalley.com": "Leven Labs, Inc. DBA Admiral", + "encourageshock.com": "Leven Labs, Inc. DBA Admiral", "encouragingthread.com": "Leven Labs, Inc. DBA Admiral", + "endlesstrust.com": "Leven Labs, Inc. DBA Admiral", "endurablebulb.com": "Leven Labs, Inc. DBA Admiral", + "energeticexample.com": "Leven Labs, Inc. DBA Admiral", "energeticladybug.com": "Leven Labs, Inc. DBA Admiral", + "engineergrape.com": "Leven Labs, Inc. DBA Admiral", "engineertrick.com": "Leven Labs, Inc. DBA Admiral", + "enigmaticblossom.com": "Leven Labs, Inc. DBA Admiral", "enigmaticcanyon.com": "Leven Labs, Inc. DBA Admiral", "enigmaticvoyage.com": "Leven Labs, Inc. DBA Admiral", "enormousearth.com": "Leven Labs, Inc. DBA Admiral", + "enormousfoot.com": "Leven Labs, Inc. DBA Admiral", + "enterdrama.com": "Leven Labs, Inc. DBA Admiral", "entertainskin.com": "Leven Labs, Inc. DBA Admiral", + "enthusiastictemper.com": "Leven Labs, Inc. DBA Admiral", "enviousshape.com": "Leven Labs, Inc. DBA Admiral", + "enviousthread.com": "Leven Labs, Inc. DBA Admiral", "equablekettle.com": "Leven Labs, Inc. DBA Admiral", + "etherealbamboo.com": "Leven Labs, Inc. DBA Admiral", "ethereallagoon.com": "Leven Labs, Inc. DBA Admiral", + "etherealpinnacle.com": "Leven Labs, Inc. DBA Admiral", + "etherealquasar.com": "Leven Labs, Inc. DBA Admiral", + "etherealripple.com": "Leven Labs, Inc. DBA Admiral", "evanescentedge.com": "Leven Labs, Inc. DBA Admiral", "evasivejar.com": "Leven Labs, Inc. DBA Admiral", "eventexistence.com": "Leven Labs, Inc. DBA Admiral", "exampleshake.com": "Leven Labs, Inc. DBA Admiral", "excitingtub.com": "Leven Labs, Inc. DBA Admiral", + "exclusivebrass.com": "Leven Labs, Inc. DBA Admiral", "executeknowledge.com": "Leven Labs, Inc. DBA Admiral", "exhibitsneeze.com": "Leven Labs, Inc. DBA Admiral", "expansioneggnog.com": "Leven Labs, Inc. DBA Admiral", "exquisiteartisanship.com": "Leven Labs, Inc. DBA Admiral", + "extractobservation.com": "Leven Labs, Inc. DBA Admiral", + "extralocker.com": "Leven Labs, Inc. DBA Admiral", + "extramonies.com": "Leven Labs, Inc. DBA Admiral", "exuberantedge.com": "Leven Labs, Inc. DBA Admiral", "facilitatebreakfast.com": "Leven Labs, Inc. DBA Admiral", + "fadechildren.com": "Leven Labs, Inc. DBA Admiral", "fadedsnow.com": "Leven Labs, Inc. DBA Admiral", "fadewaves.com": "Leven Labs, Inc. DBA Admiral", + "fairfeeling.com": "Leven Labs, Inc. DBA Admiral", "fairiesbranch.com": "Leven Labs, Inc. DBA Admiral", "fairytaleflame.com": "Leven Labs, Inc. DBA Admiral", "fallaciousfifth.com": "Leven Labs, Inc. DBA Admiral", + "falseframe.com": "Leven Labs, Inc. DBA Admiral", + "familiarrod.com": "Leven Labs, Inc. DBA Admiral", "fancyactivity.com": "Leven Labs, Inc. DBA Admiral", "fancydune.com": "Leven Labs, Inc. DBA Admiral", + "fancygrove.com": "Leven Labs, Inc. DBA Admiral", + "fangfeeling.com": "Leven Labs, Inc. DBA Admiral", + "fantastictone.com": "Leven Labs, Inc. DBA Admiral", + "farethief.com": "Leven Labs, Inc. DBA Admiral", "farmergoldfish.com": "Leven Labs, Inc. DBA Admiral", "farshake.com": "Leven Labs, Inc. DBA Admiral", "farsnails.com": "Leven Labs, Inc. DBA Admiral", "fastenfather.com": "Leven Labs, Inc. DBA Admiral", + "fasterfineart.com": "Leven Labs, Inc. DBA Admiral", + "fasterjson.com": "Leven Labs, Inc. DBA Admiral", "fatcoil.com": "Leven Labs, Inc. DBA Admiral", "faucetfoot.com": "Leven Labs, Inc. DBA Admiral", "faultycanvas.com": "Leven Labs, Inc. DBA Admiral", + "fearfulfish.com": "Leven Labs, Inc. DBA Admiral", "fearfulmint.com": "Leven Labs, Inc. DBA Admiral", "fearlessfaucet.com": "Leven Labs, Inc. DBA Admiral", + "fearlesstramp.com": "Leven Labs, Inc. DBA Admiral", "featherstage.com": "Leven Labs, Inc. DBA Admiral", + "feeblestamp.com": "Leven Labs, Inc. DBA Admiral", "feignedfaucet.com": "Leven Labs, Inc. DBA Admiral", + "fernwaycloud.com": "Leven Labs, Inc. DBA Admiral", "fertilefeeling.com": "Leven Labs, Inc. DBA Admiral", "fewjuice.com": "Leven Labs, Inc. DBA Admiral", "fewkittens.com": "Leven Labs, Inc. DBA Admiral", + "finalizeforce.com": "Leven Labs, Inc. DBA Admiral", "financefear.com": "Leven Labs, Inc. DBA Admiral", + "finestpiece.com": "Leven Labs, Inc. DBA Admiral", + "finitecube.com": "Leven Labs, Inc. DBA Admiral", + "firecatfilms.com": "Leven Labs, Inc. DBA Admiral", + "fireworkcamp.com": "Leven Labs, Inc. DBA Admiral", + "firstendpoint.com": "Leven Labs, Inc. DBA Admiral", "firstfrogs.com": "Leven Labs, Inc. DBA Admiral", + "firsttexture.com": "Leven Labs, Inc. DBA Admiral", + "fitmessage.com": "Leven Labs, Inc. DBA Admiral", + "fivesidedsquare.com": "Leven Labs, Inc. DBA Admiral", "fixedfold.com": "Leven Labs, Inc. DBA Admiral", + "flakyfeast.com": "Leven Labs, Inc. DBA Admiral", "flameuncle.com": "Leven Labs, Inc. DBA Admiral", "flimsycircle.com": "Leven Labs, Inc. DBA Admiral", "flimsythought.com": "Leven Labs, Inc. DBA Admiral", + "flippedfunnel.com": "Leven Labs, Inc. DBA Admiral", + "floodprincipal.com": "Leven Labs, Inc. DBA Admiral", "flourishingcollaboration.com": "Leven Labs, Inc. DBA Admiral", + "flourishingendeavor.com": "Leven Labs, Inc. DBA Admiral", "flourishinginnovation.com": "Leven Labs, Inc. DBA Admiral", "flourishingpartnership.com": "Leven Labs, Inc. DBA Admiral", + "flowersornament.com": "Leven Labs, Inc. DBA Admiral", "flowerstreatment.com": "Leven Labs, Inc. DBA Admiral", "flowerycreature.com": "Leven Labs, Inc. DBA Admiral", "floweryfact.com": "Leven Labs, Inc. DBA Admiral", "floweryflavor.com": "Leven Labs, Inc. DBA Admiral", + "floweryoperation.com": "Leven Labs, Inc. DBA Admiral", "flutteringfireman.com": "Leven Labs, Inc. DBA Admiral", + "foambench.com": "Leven Labs, Inc. DBA Admiral", "followborder.com": "Leven Labs, Inc. DBA Admiral", + "forecasttiger.com": "Leven Labs, Inc. DBA Admiral", + "foretellfifth.com": "Leven Labs, Inc. DBA Admiral", + "forevergears.com": "Leven Labs, Inc. DBA Admiral", + "forgetfulflowers.com": "Leven Labs, Inc. DBA Admiral", "forgetfulsnail.com": "Leven Labs, Inc. DBA Admiral", "fortunatemark.com": "Leven Labs, Inc. DBA Admiral", + "fractalcoast.com": "Leven Labs, Inc. DBA Admiral", "frailfruit.com": "Leven Labs, Inc. DBA Admiral", + "framebanana.com": "Leven Labs, Inc. DBA Admiral", "franticroof.com": "Leven Labs, Inc. DBA Admiral", + "frantictrail.com": "Leven Labs, Inc. DBA Admiral", + "frazzleart.com": "Leven Labs, Inc. DBA Admiral", + "freakyglass.com": "Leven Labs, Inc. DBA Admiral", "freezingbuilding.com": "Leven Labs, Inc. DBA Admiral", "frequentflesh.com": "Leven Labs, Inc. DBA Admiral", "friendlycrayon.com": "Leven Labs, Inc. DBA Admiral", + "friendlyfold.com": "Leven Labs, Inc. DBA Admiral", "friendwool.com": "Leven Labs, Inc. DBA Admiral", + "frightenedpotato.com": "Leven Labs, Inc. DBA Admiral", + "frogator.com": "Leven Labs, Inc. DBA Admiral", + "frogtray.com": "Leven Labs, Inc. DBA Admiral", "fronttoad.com": "Leven Labs, Inc. DBA Admiral", + "frugalfiestas.com": "Leven Labs, Inc. DBA Admiral", "fumblingform.com": "Leven Labs, Inc. DBA Admiral", + "functionalcrown.com": "Leven Labs, Inc. DBA Admiral", "functionalfeather.com": "Leven Labs, Inc. DBA Admiral", + "funoverbored.com": "Leven Labs, Inc. DBA Admiral", + "funoverflow.com": "Leven Labs, Inc. DBA Admiral", + "furnstudio.com": "Leven Labs, Inc. DBA Admiral", "furryfork.com": "Leven Labs, Inc. DBA Admiral", + "furryhorses.com": "Leven Labs, Inc. DBA Admiral", + "futuristicapparatus.com": "Leven Labs, Inc. DBA Admiral", + "futuristicfairies.com": "Leven Labs, Inc. DBA Admiral", "futuristicfifth.com": "Leven Labs, Inc. DBA Admiral", "futuristicframe.com": "Leven Labs, Inc. DBA Admiral", + "fuzzyaudio.com": "Leven Labs, Inc. DBA Admiral", "fuzzybasketball.com": "Leven Labs, Inc. DBA Admiral", "fuzzyerror.com": "Leven Labs, Inc. DBA Admiral", + "fvl1f.pw": "Leven Labs, Inc. DBA Admiral", "gammamaximum.com": "Leven Labs, Inc. DBA Admiral", + "gardenovens.com": "Leven Labs, Inc. DBA Admiral", "gaudyairplane.com": "Leven Labs, Inc. DBA Admiral", + "geekactive.com": "Leven Labs, Inc. DBA Admiral", + "generalprose.com": "Leven Labs, Inc. DBA Admiral", "generateoffice.com": "Leven Labs, Inc. DBA Admiral", "giantsvessel.com": "Leven Labs, Inc. DBA Admiral", "giddycoat.com": "Leven Labs, Inc. DBA Admiral", "giraffepiano.com": "Leven Labs, Inc. DBA Admiral", + "gitcrumbs.com": "Leven Labs, Inc. DBA Admiral", "givevacation.com": "Leven Labs, Inc. DBA Admiral", + "gladglen.com": "Leven Labs, Inc. DBA Admiral", "gladysway.com": "Leven Labs, Inc. DBA Admiral", + "glamhawk.com": "Leven Labs, Inc. DBA Admiral", "gleamingcow.com": "Leven Labs, Inc. DBA Admiral", + "gleaminghaven.com": "Leven Labs, Inc. DBA Admiral", "glisteningguide.com": "Leven Labs, Inc. DBA Admiral", + "glisteningsign.com": "Leven Labs, Inc. DBA Admiral", "glitteringbrook.com": "Leven Labs, Inc. DBA Admiral", "gloriousbeef.com": "Leven Labs, Inc. DBA Admiral", + "glowingmeadow.com": "Leven Labs, Inc. DBA Admiral", + "gluedpixel.com": "Leven Labs, Inc. DBA Admiral", "goldfishgrowth.com": "Leven Labs, Inc. DBA Admiral", "gondolagnome.com": "Leven Labs, Inc. DBA Admiral", + "goodbark.com": "Leven Labs, Inc. DBA Admiral", "gorgeousedge.com": "Leven Labs, Inc. DBA Admiral", "gracefulmilk.com": "Leven Labs, Inc. DBA Admiral", "grainmass.com": "Leven Labs, Inc. DBA Admiral", "grandfatherguitar.com": "Leven Labs, Inc. DBA Admiral", + "gravitygive.com": "Leven Labs, Inc. DBA Admiral", + "gravitykick.com": "Leven Labs, Inc. DBA Admiral", "grayoranges.com": "Leven Labs, Inc. DBA Admiral", "grayreceipt.com": "Leven Labs, Inc. DBA Admiral", "greasysquare.com": "Leven Labs, Inc. DBA Admiral", + "greyinstrument.com": "Leven Labs, Inc. DBA Admiral", + "gripcorn.com": "Leven Labs, Inc. DBA Admiral", + "groovyornament.com": "Leven Labs, Inc. DBA Admiral", + "grouchybrothers.com": "Leven Labs, Inc. DBA Admiral", "grouchypush.com": "Leven Labs, Inc. DBA Admiral", "grumpydime.com": "Leven Labs, Inc. DBA Admiral", + "grumpydrawer.com": "Leven Labs, Inc. DBA Admiral", "guardeddirection.com": "Leven Labs, Inc. DBA Admiral", + "guardedschool.com": "Leven Labs, Inc. DBA Admiral", + "guessdetail.com": "Leven Labs, Inc. DBA Admiral", "guidecent.com": "Leven Labs, Inc. DBA Admiral", + "guildalpha.com": "Leven Labs, Inc. DBA Admiral", "guiltlessbasketball.com": "Leven Labs, Inc. DBA Admiral", "gulliblegrip.com": "Leven Labs, Inc. DBA Admiral", + "gustocooking.com": "Leven Labs, Inc. DBA Admiral", "gustygrandmother.com": "Leven Labs, Inc. DBA Admiral", + "h78xb.pw": "Leven Labs, Inc. DBA Admiral", + "habitualhumor.com": "Leven Labs, Inc. DBA Admiral", "halcyoncanyon.com": "Leven Labs, Inc. DBA Admiral", "halcyonsculpture.com": "Leven Labs, Inc. DBA Admiral", "hallowedinvention.com": "Leven Labs, Inc. DBA Admiral", @@ -51889,64 +60361,122 @@ "haltingdivision.com": "Leven Labs, Inc. DBA Admiral", "haltinggold.com": "Leven Labs, Inc. DBA Admiral", "hammerhearing.com": "Leven Labs, Inc. DBA Admiral", + "handleteeth.com": "Leven Labs, Inc. DBA Admiral", + "handnorth.com": "Leven Labs, Inc. DBA Admiral", "handsomehose.com": "Leven Labs, Inc. DBA Admiral", + "handsomeindustry.com": "Leven Labs, Inc. DBA Admiral", "handsomelyhealth.com": "Leven Labs, Inc. DBA Admiral", "handsomelythumb.com": "Leven Labs, Inc. DBA Admiral", + "handsomeyam.com": "Leven Labs, Inc. DBA Admiral", "handyfield.com": "Leven Labs, Inc. DBA Admiral", "handyfireman.com": "Leven Labs, Inc. DBA Admiral", "handyincrease.com": "Leven Labs, Inc. DBA Admiral", "haplesshydrant.com": "Leven Labs, Inc. DBA Admiral", "haplessland.com": "Leven Labs, Inc. DBA Admiral", + "happysponge.com": "Leven Labs, Inc. DBA Admiral", "harborcaption.com": "Leven Labs, Inc. DBA Admiral", + "harborcub.com": "Leven Labs, Inc. DBA Admiral", + "harmonicbamboo.com": "Leven Labs, Inc. DBA Admiral", + "harmonywing.com": "Leven Labs, Inc. DBA Admiral", "hatefulrequest.com": "Leven Labs, Inc. DBA Admiral", "headydegree.com": "Leven Labs, Inc. DBA Admiral", + "headyhook.com": "Leven Labs, Inc. DBA Admiral", + "healflowers.com": "Leven Labs, Inc. DBA Admiral", + "hearinglizards.com": "Leven Labs, Inc. DBA Admiral", "heartbreakingmind.com": "Leven Labs, Inc. DBA Admiral", "hearthorn.com": "Leven Labs, Inc. DBA Admiral", + "heavydetail.com": "Leven Labs, Inc. DBA Admiral", "heavyplayground.com": "Leven Labs, Inc. DBA Admiral", "helpcollar.com": "Leven Labs, Inc. DBA Admiral", + "helpflame.com": "Leven Labs, Inc. DBA Admiral", + "hfc195b.com": "Leven Labs, Inc. DBA Admiral", + "highfalutinbox.com": "Leven Labs, Inc. DBA Admiral", "highfalutinhoney.com": "Leven Labs, Inc. DBA Admiral", + "hilariouszinc.com": "Leven Labs, Inc. DBA Admiral", "historicalbeam.com": "Leven Labs, Inc. DBA Admiral", "hocgeese.com": "Leven Labs, Inc. DBA Admiral", "hollowafterthought.com": "Leven Labs, Inc. DBA Admiral", + "homelycrown.com": "Leven Labs, Inc. DBA Admiral", "honeybulb.com": "Leven Labs, Inc. DBA Admiral", + "honeywhipped.com": "Leven Labs, Inc. DBA Admiral", + "honorablehydrant.com": "Leven Labs, Inc. DBA Admiral", "honorableland.com": "Leven Labs, Inc. DBA Admiral", "horsenectar.com": "Leven Labs, Inc. DBA Admiral", "hospitablehall.com": "Leven Labs, Inc. DBA Admiral", "hospitablehat.com": "Leven Labs, Inc. DBA Admiral", + "howdyinbox.com": "Leven Labs, Inc. DBA Admiral", + "humdrumhobbies.com": "Leven Labs, Inc. DBA Admiral", "humdrumtouch.com": "Leven Labs, Inc. DBA Admiral", + "hurtgrape.com": "Leven Labs, Inc. DBA Admiral", + "hypnoticwound.com": "Leven Labs, Inc. DBA Admiral", "hystericalcloth.com": "Leven Labs, Inc. DBA Admiral", + "hystericalfinger.com": "Leven Labs, Inc. DBA Admiral", + "i9w8p.pw": "Leven Labs, Inc. DBA Admiral", + "idolscene.com": "Leven Labs, Inc. DBA Admiral", "idyllicjazz.com": "Leven Labs, Inc. DBA Admiral", "illinvention.com": "Leven Labs, Inc. DBA Admiral", + "illustriousoatmeal.com": "Leven Labs, Inc. DBA Admiral", + "immensehoney.com": "Leven Labs, Inc. DBA Admiral", + "imminentshake.com": "Leven Labs, Inc. DBA Admiral", "importantmeat.com": "Leven Labs, Inc. DBA Admiral", + "importedincrease.com": "Leven Labs, Inc. DBA Admiral", + "importedinsect.com": "Leven Labs, Inc. DBA Admiral", + "importlocate.com": "Leven Labs, Inc. DBA Admiral", "impossibleexpansion.com": "Leven Labs, Inc. DBA Admiral", + "impossiblemove.com": "Leven Labs, Inc. DBA Admiral", "impulsejewel.com": "Leven Labs, Inc. DBA Admiral", "impulselumber.com": "Leven Labs, Inc. DBA Admiral", + "incomehippo.com": "Leven Labs, Inc. DBA Admiral", "incompetentjoke.com": "Leven Labs, Inc. DBA Admiral", "inconclusiveaction.com": "Leven Labs, Inc. DBA Admiral", + "infamousstream.com": "Leven Labs, Inc. DBA Admiral", + "innocentlamp.com": "Leven Labs, Inc. DBA Admiral", + "innocentwax.com": "Leven Labs, Inc. DBA Admiral", "inputicicle.com": "Leven Labs, Inc. DBA Admiral", "inquisitiveice.com": "Leven Labs, Inc. DBA Admiral", + "inquisitiveinvention.com": "Leven Labs, Inc. DBA Admiral", "intelligentscissors.com": "Leven Labs, Inc. DBA Admiral", + "intentlens.com": "Leven Labs, Inc. DBA Admiral", + "interestdust.com": "Leven Labs, Inc. DBA Admiral", "internalcondition.com": "Leven Labs, Inc. DBA Admiral", "internalsink.com": "Leven Labs, Inc. DBA Admiral", + "iotapool.com": "Leven Labs, Inc. DBA Admiral", "irritatingfog.com": "Leven Labs, Inc. DBA Admiral", + "itemslice.com": "Leven Labs, Inc. DBA Admiral", + "ivykiosk.com": "Leven Labs, Inc. DBA Admiral", "j93557g.com": "Leven Labs, Inc. DBA Admiral", + "jadeitite.com": "Leven Labs, Inc. DBA Admiral", + "jaderooster.com": "Leven Labs, Inc. DBA Admiral", + "jailbulb.com": "Leven Labs, Inc. DBA Admiral", + "joblessdrum.com": "Leven Labs, Inc. DBA Admiral", "jollylens.com": "Leven Labs, Inc. DBA Admiral", "joyfulkeen.com": "Leven Labs, Inc. DBA Admiral", + "joyoussurprise.com": "Leven Labs, Inc. DBA Admiral", "jubilantaura.com": "Leven Labs, Inc. DBA Admiral", "jubilantcanyon.com": "Leven Labs, Inc. DBA Admiral", "jubilantcascade.com": "Leven Labs, Inc. DBA Admiral", "jubilantglimmer.com": "Leven Labs, Inc. DBA Admiral", "jubilanttempest.com": "Leven Labs, Inc. DBA Admiral", "jubilantwhisper.com": "Leven Labs, Inc. DBA Admiral", + "justicejudo.com": "Leven Labs, Inc. DBA Admiral", + "k54nw.pw": "Leven Labs, Inc. DBA Admiral", "kaputquill.com": "Leven Labs, Inc. DBA Admiral", "keenquill.com": "Leven Labs, Inc. DBA Admiral", + "kindhush.com": "Leven Labs, Inc. DBA Admiral", + "kitesquirrel.com": "Leven Labs, Inc. DBA Admiral", "knitstamp.com": "Leven Labs, Inc. DBA Admiral", "knottyswing.com": "Leven Labs, Inc. DBA Admiral", + "laboredlight.com": "Leven Labs, Inc. DBA Admiral", "laboredlocket.com": "Leven Labs, Inc. DBA Admiral", "lameletters.com": "Leven Labs, Inc. DBA Admiral", + "lamplow.com": "Leven Labs, Inc. DBA Admiral", "largebrass.com": "Leven Labs, Inc. DBA Admiral", + "lasttaco.com": "Leven Labs, Inc. DBA Admiral", "laughablelizards.com": "Leven Labs, Inc. DBA Admiral", + "leaplunchroom.com": "Leven Labs, Inc. DBA Admiral", "leftliquid.com": "Leven Labs, Inc. DBA Admiral", + "lemonpackage.com": "Leven Labs, Inc. DBA Admiral", + "lemonsandjoy.com": "Leven Labs, Inc. DBA Admiral", "liftedknowledge.com": "Leven Labs, Inc. DBA Admiral", "lightenafterthought.com": "Leven Labs, Inc. DBA Admiral", "lighttalon.com": "Leven Labs, Inc. DBA Admiral", @@ -51961,28 +60491,50 @@ "looseloaf.com": "Leven Labs, Inc. DBA Admiral", "lorenzourban.com": "Leven Labs, Inc. DBA Admiral", "losslace.com": "Leven Labs, Inc. DBA Admiral", + "loudlunch.com": "Leven Labs, Inc. DBA Admiral", "lovelydrum.com": "Leven Labs, Inc. DBA Admiral", + "loveseashore.com": "Leven Labs, Inc. DBA Admiral", + "lp3tdqle.com": "Leven Labs, Inc. DBA Admiral", "ludicrousarch.com": "Leven Labs, Inc. DBA Admiral", + "lumberamount.com": "Leven Labs, Inc. DBA Admiral", "luminousboulevard.com": "Leven Labs, Inc. DBA Admiral", "luminouscatalyst.com": "Leven Labs, Inc. DBA Admiral", + "luminoussculptor.com": "Leven Labs, Inc. DBA Admiral", + "lumpygnome.com": "Leven Labs, Inc. DBA Admiral", "lumpylumber.com": "Leven Labs, Inc. DBA Admiral", "lunchroomlock.com": "Leven Labs, Inc. DBA Admiral", "lustroushaven.com": "Leven Labs, Inc. DBA Admiral", + "lyricshook.com": "Leven Labs, Inc. DBA Admiral", "maddeningpowder.com": "Leven Labs, Inc. DBA Admiral", + "madebyintent.com": "Leven Labs, Inc. DBA Admiral", "magicaljoin.com": "Leven Labs, Inc. DBA Admiral", + "magnetairport.com": "Leven Labs, Inc. DBA Admiral", + "majesticmountainrange.com": "Leven Labs, Inc. DBA Admiral", "majesticwaterscape.com": "Leven Labs, Inc. DBA Admiral", "majesticwilderness.com": "Leven Labs, Inc. DBA Admiral", "maliciousmusic.com": "Leven Labs, Inc. DBA Admiral", + "managedpush.com": "Leven Labs, Inc. DBA Admiral", + "mantrafox.com": "Leven Labs, Inc. DBA Admiral", + "marblediscussion.com": "Leven Labs, Inc. DBA Admiral", + "markahouse.com": "Leven Labs, Inc. DBA Admiral", + "markedmeasure.com": "Leven Labs, Inc. DBA Admiral", "marketspiders.com": "Leven Labs, Inc. DBA Admiral", "marriedbelief.com": "Leven Labs, Inc. DBA Admiral", + "marriedmailbox.com": "Leven Labs, Inc. DBA Admiral", "marriedvalue.com": "Leven Labs, Inc. DBA Admiral", + "massivemark.com": "Leven Labs, Inc. DBA Admiral", "materialisticmoon.com": "Leven Labs, Inc. DBA Admiral", + "materialmilk.com": "Leven Labs, Inc. DBA Admiral", "materialparcel.com": "Leven Labs, Inc. DBA Admiral", "materialplayground.com": "Leven Labs, Inc. DBA Admiral", "meadowlullaby.com": "Leven Labs, Inc. DBA Admiral", "measlymiddle.com": "Leven Labs, Inc. DBA Admiral", "meatydime.com": "Leven Labs, Inc. DBA Admiral", "meddleplant.com": "Leven Labs, Inc. DBA Admiral", + "mediatescarf.com": "Leven Labs, Inc. DBA Admiral", + "mediumshort.com": "Leven Labs, Inc. DBA Admiral", + "mellowhush.com": "Leven Labs, Inc. DBA Admiral", + "mellowmailbox.com": "Leven Labs, Inc. DBA Admiral", "melodiouschorus.com": "Leven Labs, Inc. DBA Admiral", "melodiouscomposition.com": "Leven Labs, Inc. DBA Admiral", "meltmilk.com": "Leven Labs, Inc. DBA Admiral", @@ -51994,23 +60546,37 @@ "merequartz.com": "Leven Labs, Inc. DBA Admiral", "merryopal.com": "Leven Labs, Inc. DBA Admiral", "merryvault.com": "Leven Labs, Inc. DBA Admiral", + "messagenovice.com": "Leven Labs, Inc. DBA Admiral", + "messyoranges.com": "Leven Labs, Inc. DBA Admiral", "mightyspiders.com": "Leven Labs, Inc. DBA Admiral", + "mimosamajor.com": "Leven Labs, Inc. DBA Admiral", + "mindfulgem.com": "Leven Labs, Inc. DBA Admiral", "minorcattle.com": "Leven Labs, Inc. DBA Admiral", + "minusmental.com": "Leven Labs, Inc. DBA Admiral", "minuteburst.com": "Leven Labs, Inc. DBA Admiral", + "miscreantmoon.com": "Leven Labs, Inc. DBA Admiral", + "mistyhorizon.com": "Leven Labs, Inc. DBA Admiral", + "mittencattle.com": "Leven Labs, Inc. DBA Admiral", "mixedreading.com": "Leven Labs, Inc. DBA Admiral", "modularmental.com": "Leven Labs, Inc. DBA Admiral", "monacobeatles.com": "Leven Labs, Inc. DBA Admiral", "moorshoes.com": "Leven Labs, Inc. DBA Admiral", "motionflowers.com": "Leven Labs, Inc. DBA Admiral", "motionlessbag.com": "Leven Labs, Inc. DBA Admiral", + "motionlessbelief.com": "Leven Labs, Inc. DBA Admiral", "motionlessmeeting.com": "Leven Labs, Inc. DBA Admiral", "movemeal.com": "Leven Labs, Inc. DBA Admiral", + "muddledaftermath.com": "Leven Labs, Inc. DBA Admiral", + "muddledmemory.com": "Leven Labs, Inc. DBA Admiral", "mundanenail.com": "Leven Labs, Inc. DBA Admiral", + "mundanepollution.com": "Leven Labs, Inc. DBA Admiral", "mushywaste.com": "Leven Labs, Inc. DBA Admiral", "muteknife.com": "Leven Labs, Inc. DBA Admiral", + "mutemailbox.com": "Leven Labs, Inc. DBA Admiral", "mysticalagoon.com": "Leven Labs, Inc. DBA Admiral", "naivestatement.com": "Leven Labs, Inc. DBA Admiral", "nappyattack.com": "Leven Labs, Inc. DBA Admiral", + "nappyneck.com": "Leven Labs, Inc. DBA Admiral", "neatshade.com": "Leven Labs, Inc. DBA Admiral", "nebulacrescent.com": "Leven Labs, Inc. DBA Admiral", "nebulajubilee.com": "Leven Labs, Inc. DBA Admiral", @@ -52019,93 +60585,171 @@ "nebulousquasar.com": "Leven Labs, Inc. DBA Admiral", "nebulousripple.com": "Leven Labs, Inc. DBA Admiral", "needlessnorth.com": "Leven Labs, Inc. DBA Admiral", + "needyneedle.com": "Leven Labs, Inc. DBA Admiral", + "neighborlywatch.com": "Leven Labs, Inc. DBA Admiral", "nervoussummer.com": "Leven Labs, Inc. DBA Admiral", + "niftygraphs.com": "Leven Labs, Inc. DBA Admiral", "niftyhospital.com": "Leven Labs, Inc. DBA Admiral", + "niftyjelly.com": "Leven Labs, Inc. DBA Admiral", "nightwound.com": "Leven Labs, Inc. DBA Admiral", + "nimbleplot.com": "Leven Labs, Inc. DBA Admiral", "nocturnalloom.com": "Leven Labs, Inc. DBA Admiral", + "nocturnalmystique.com": "Leven Labs, Inc. DBA Admiral", + "noiselessplough.com": "Leven Labs, Inc. DBA Admiral", + "nonchalantnerve.com": "Leven Labs, Inc. DBA Admiral", "nondescriptcrowd.com": "Leven Labs, Inc. DBA Admiral", "nondescriptnote.com": "Leven Labs, Inc. DBA Admiral", + "nondescriptstocking.com": "Leven Labs, Inc. DBA Admiral", + "nostalgicknot.com": "Leven Labs, Inc. DBA Admiral", "nostalgicneed.com": "Leven Labs, Inc. DBA Admiral", + "notifyglass.com": "Leven Labs, Inc. DBA Admiral", + "nudgeduck.com": "Leven Labs, Inc. DBA Admiral", + "nullnorth.com": "Leven Labs, Inc. DBA Admiral", "numberlessring.com": "Leven Labs, Inc. DBA Admiral", + "numerousnest.com": "Leven Labs, Inc. DBA Admiral", "nutritiousbean.com": "Leven Labs, Inc. DBA Admiral", "nuttyorganization.com": "Leven Labs, Inc. DBA Admiral", "oafishchance.com": "Leven Labs, Inc. DBA Admiral", + "oafishobservation.com": "Leven Labs, Inc. DBA Admiral", "obscenesidewalk.com": "Leven Labs, Inc. DBA Admiral", + "observantice.com": "Leven Labs, Inc. DBA Admiral", "oldfashionedoffer.com": "Leven Labs, Inc. DBA Admiral", + "omgthink.com": "Leven Labs, Inc. DBA Admiral", + "omniscientfeeling.com": "Leven Labs, Inc. DBA Admiral", + "onlywoofs.com": "Leven Labs, Inc. DBA Admiral", "opalquill.com": "Leven Labs, Inc. DBA Admiral", "operationchicken.com": "Leven Labs, Inc. DBA Admiral", + "operationnail.com": "Leven Labs, Inc. DBA Admiral", + "oppositeoperation.com": "Leven Labs, Inc. DBA Admiral", "optimallimit.com": "Leven Labs, Inc. DBA Admiral", "opulentsylvan.com": "Leven Labs, Inc. DBA Admiral", "orientedargument.com": "Leven Labs, Inc. DBA Admiral", + "orionember.com": "Leven Labs, Inc. DBA Admiral", + "ourblogthing.com": "Leven Labs, Inc. DBA Admiral", + "outgoinggiraffe.com": "Leven Labs, Inc. DBA Admiral", + "outsidevibe.com": "Leven Labs, Inc. DBA Admiral", "outstandingincome.com": "Leven Labs, Inc. DBA Admiral", "outstandingsnails.com": "Leven Labs, Inc. DBA Admiral", "overconfidentfood.com": "Leven Labs, Inc. DBA Admiral", + "overkick.com": "Leven Labs, Inc. DBA Admiral", + "overratedchalk.com": "Leven Labs, Inc. DBA Admiral", + "owlsr.us": "Leven Labs, Inc. DBA Admiral", + "oxygenfuse.com": "Leven Labs, Inc. DBA Admiral", + "pailcrime.com": "Leven Labs, Inc. DBA Admiral", "pailpatch.com": "Leven Labs, Inc. DBA Admiral", "painstakingpickle.com": "Leven Labs, Inc. DBA Admiral", + "paintpear.com": "Leven Labs, Inc. DBA Admiral", + "paleleaf.com": "Leven Labs, Inc. DBA Admiral", "pamelarandom.com": "Leven Labs, Inc. DBA Admiral", "panickycurtain.com": "Leven Labs, Inc. DBA Admiral", "panickypancake.com": "Leven Labs, Inc. DBA Admiral", "panoramicplane.com": "Leven Labs, Inc. DBA Admiral", "parallelbulb.com": "Leven Labs, Inc. DBA Admiral", "parchedsofa.com": "Leven Labs, Inc. DBA Admiral", + "pardonpopular.com": "Leven Labs, Inc. DBA Admiral", "parentpicture.com": "Leven Labs, Inc. DBA Admiral", + "parsimoniouspolice.com": "Leven Labs, Inc. DBA Admiral", "partplanes.com": "Leven Labs, Inc. DBA Admiral", "passivepolo.com": "Leven Labs, Inc. DBA Admiral", + "pastoralroad.com": "Leven Labs, Inc. DBA Admiral", + "pawsnug.com": "Leven Labs, Inc. DBA Admiral", "peacefullimit.com": "Leven Labs, Inc. DBA Admiral", + "pedromister.com": "Leven Labs, Inc. DBA Admiral", + "pedropanther.com": "Leven Labs, Inc. DBA Admiral", + "perceivequarter.com": "Leven Labs, Inc. DBA Admiral", + "perkyjade.com": "Leven Labs, Inc. DBA Admiral", "petiteumbrella.com": "Leven Labs, Inc. DBA Admiral", + "philippinch.com": "Leven Labs, Inc. DBA Admiral", + "photographpan.com": "Leven Labs, Inc. DBA Admiral", + "piespower.com": "Leven Labs, Inc. DBA Admiral", "piquantgrove.com": "Leven Labs, Inc. DBA Admiral", "piquantmeadow.com": "Leven Labs, Inc. DBA Admiral", + "piquantpigs.com": "Leven Labs, Inc. DBA Admiral", + "piquantprice.com": "Leven Labs, Inc. DBA Admiral", "piquantvortex.com": "Leven Labs, Inc. DBA Admiral", + "pixeledhub.com": "Leven Labs, Inc. DBA Admiral", + "pizzasnut.com": "Leven Labs, Inc. DBA Admiral", + "placeframe.com": "Leven Labs, Inc. DBA Admiral", "placidactivity.com": "Leven Labs, Inc. DBA Admiral", "placidperson.com": "Leven Labs, Inc. DBA Admiral", "planebasin.com": "Leven Labs, Inc. DBA Admiral", "plantdigestion.com": "Leven Labs, Inc. DBA Admiral", "playfulriver.com": "Leven Labs, Inc. DBA Admiral", "pleasantpump.com": "Leven Labs, Inc. DBA Admiral", + "plotparent.com": "Leven Labs, Inc. DBA Admiral", "plotrabbit.com": "Leven Labs, Inc. DBA Admiral", "pluckypocket.com": "Leven Labs, Inc. DBA Admiral", "pluckyzone.com": "Leven Labs, Inc. DBA Admiral", "pocketfaucet.com": "Leven Labs, Inc. DBA Admiral", "poeticpackage.com": "Leven Labs, Inc. DBA Admiral", "pointdigestion.com": "Leven Labs, Inc. DBA Admiral", + "pointlesshour.com": "Leven Labs, Inc. DBA Admiral", "pointlesspocket.com": "Leven Labs, Inc. DBA Admiral", "pointlessprofit.com": "Leven Labs, Inc. DBA Admiral", + "pointlessrifle.com": "Leven Labs, Inc. DBA Admiral", + "polarismagnet.com": "Leven Labs, Inc. DBA Admiral", "polishedcrescent.com": "Leven Labs, Inc. DBA Admiral", "polishedfolly.com": "Leven Labs, Inc. DBA Admiral", "politeplanes.com": "Leven Labs, Inc. DBA Admiral", + "politicalflip.com": "Leven Labs, Inc. DBA Admiral", "politicalporter.com": "Leven Labs, Inc. DBA Admiral", "popplantation.com": "Leven Labs, Inc. DBA Admiral", "possibleboats.com": "Leven Labs, Inc. DBA Admiral", "possiblepencil.com": "Leven Labs, Inc. DBA Admiral", "potatoinvention.com": "Leven Labs, Inc. DBA Admiral", "powderjourney.com": "Leven Labs, Inc. DBA Admiral", + "powerfulblends.com": "Leven Labs, Inc. DBA Admiral", "powerfulcopper.com": "Leven Labs, Inc. DBA Admiral", "preciousplanes.com": "Leven Labs, Inc. DBA Admiral", "predictplate.com": "Leven Labs, Inc. DBA Admiral", + "prefixpatriot.com": "Leven Labs, Inc. DBA Admiral", "prepareplanes.com": "Leven Labs, Inc. DBA Admiral", + "presetrabbits.com": "Leven Labs, Inc. DBA Admiral", + "previousplayground.com": "Leven Labs, Inc. DBA Admiral", + "previouspotato.com": "Leven Labs, Inc. DBA Admiral", "priceypies.com": "Leven Labs, Inc. DBA Admiral", "pricklydebt.com": "Leven Labs, Inc. DBA Admiral", "pricklypollution.com": "Leven Labs, Inc. DBA Admiral", "pristinegale.com": "Leven Labs, Inc. DBA Admiral", + "probablepartner.com": "Leven Labs, Inc. DBA Admiral", "processplantation.com": "Leven Labs, Inc. DBA Admiral", + "producepickle.com": "Leven Labs, Inc. DBA Admiral", + "productsurfer.com": "Leven Labs, Inc. DBA Admiral", + "profitrumour.com": "Leven Labs, Inc. DBA Admiral", "profusesupport.com": "Leven Labs, Inc. DBA Admiral", + "promiseair.com": "Leven Labs, Inc. DBA Admiral", + "proofconvert.com": "Leven Labs, Inc. DBA Admiral", + "propertypotato.com": "Leven Labs, Inc. DBA Admiral", "protestcopy.com": "Leven Labs, Inc. DBA Admiral", "psychedelicarithmetic.com": "Leven Labs, Inc. DBA Admiral", + "psychedelicchess.com": "Leven Labs, Inc. DBA Admiral", "publicsofa.com": "Leven Labs, Inc. DBA Admiral", + "puffyloss.com": "Leven Labs, Inc. DBA Admiral", + "puffypaste.com": "Leven Labs, Inc. DBA Admiral", + "puffypull.com": "Leven Labs, Inc. DBA Admiral", "puffypurpose.com": "Leven Labs, Inc. DBA Admiral", "pulsatingmeadow.com": "Leven Labs, Inc. DBA Admiral", "pumpedpancake.com": "Leven Labs, Inc. DBA Admiral", + "pumpedpurpose.com": "Leven Labs, Inc. DBA Admiral", "punyplant.com": "Leven Labs, Inc. DBA Admiral", + "puppytooth.com": "Leven Labs, Inc. DBA Admiral", "purposepipe.com": "Leven Labs, Inc. DBA Admiral", + "quacksquirrel.com": "Leven Labs, Inc. DBA Admiral", + "quaintcan.com": "Leven Labs, Inc. DBA Admiral", "quaintlake.com": "Leven Labs, Inc. DBA Admiral", + "quantumlagoon.com": "Leven Labs, Inc. DBA Admiral", + "quantumshine.com": "Leven Labs, Inc. DBA Admiral", + "queenskart.com": "Leven Labs, Inc. DBA Admiral", "quietknowledge.com": "Leven Labs, Inc. DBA Admiral", "quillkick.com": "Leven Labs, Inc. DBA Admiral", "quirkybliss.com": "Leven Labs, Inc. DBA Admiral", "quirkysugar.com": "Leven Labs, Inc. DBA Admiral", + "quixoticnebula.com": "Leven Labs, Inc. DBA Admiral", "quizzicalpartner.com": "Leven Labs, Inc. DBA Admiral", "quizzicalzephyr.com": "Leven Labs, Inc. DBA Admiral", "rabbitbreath.com": "Leven Labs, Inc. DBA Admiral", "rabbitrifle.com": "Leven Labs, Inc. DBA Admiral", + "radiantcanopy.com": "Leven Labs, Inc. DBA Admiral", "radiantlullaby.com": "Leven Labs, Inc. DBA Admiral", "radiateprose.com": "Leven Labs, Inc. DBA Admiral", "railwaygiraffe.com": "Leven Labs, Inc. DBA Admiral", @@ -52117,21 +60761,32 @@ "rangecake.com": "Leven Labs, Inc. DBA Admiral", "rangeplayground.com": "Leven Labs, Inc. DBA Admiral", "raresummer.com": "Leven Labs, Inc. DBA Admiral", + "reactjspdf.com": "Leven Labs, Inc. DBA Admiral", + "readingguilt.com": "Leven Labs, Inc. DBA Admiral", "readymoon.com": "Leven Labs, Inc. DBA Admiral", + "readysnails.com": "Leven Labs, Inc. DBA Admiral", + "realizedoor.com": "Leven Labs, Inc. DBA Admiral", + "realizerecess.com": "Leven Labs, Inc. DBA Admiral", + "rebelclover.com": "Leven Labs, Inc. DBA Admiral", "rebelhen.com": "Leven Labs, Inc. DBA Admiral", "rebelsubway.com": "Leven Labs, Inc. DBA Admiral", "rebelswing.com": "Leven Labs, Inc. DBA Admiral", + "receiptcent.com": "Leven Labs, Inc. DBA Admiral", + "receptiveink.com": "Leven Labs, Inc. DBA Admiral", "receptivereaction.com": "Leven Labs, Inc. DBA Admiral", "recessrain.com": "Leven Labs, Inc. DBA Admiral", "reconditeprison.com": "Leven Labs, Inc. DBA Admiral", "reconditerake.com": "Leven Labs, Inc. DBA Admiral", "reconditerespect.com": "Leven Labs, Inc. DBA Admiral", "reflectivestatement.com": "Leven Labs, Inc. DBA Admiral", + "refundradar.com": "Leven Labs, Inc. DBA Admiral", "regularplants.com": "Leven Labs, Inc. DBA Admiral", "regulatesleet.com": "Leven Labs, Inc. DBA Admiral", "rehabilitatereason.com": "Leven Labs, Inc. DBA Admiral", "relationrest.com": "Leven Labs, Inc. DBA Admiral", + "reloadphoto.com": "Leven Labs, Inc. DBA Admiral", "rememberdiscussion.com": "Leven Labs, Inc. DBA Admiral", + "rentinfinity.com": "Leven Labs, Inc. DBA Admiral", "repeatsweater.com": "Leven Labs, Inc. DBA Admiral", "replaceroute.com": "Leven Labs, Inc. DBA Admiral", "resonantbrush.com": "Leven Labs, Inc. DBA Admiral", @@ -52141,57 +60796,92 @@ "restrainstorm.com": "Leven Labs, Inc. DBA Admiral", "restructureinvention.com": "Leven Labs, Inc. DBA Admiral", "retrievemint.com": "Leven Labs, Inc. DBA Admiral", + "rhetoricalactivity.com": "Leven Labs, Inc. DBA Admiral", "rhetoricalloss.com": "Leven Labs, Inc. DBA Admiral", "rhetoricalveil.com": "Leven Labs, Inc. DBA Admiral", "rhymezebra.com": "Leven Labs, Inc. DBA Admiral", + "rhythmrule.com": "Leven Labs, Inc. DBA Admiral", "richstring.com": "Leven Labs, Inc. DBA Admiral", "righteouscrayon.com": "Leven Labs, Inc. DBA Admiral", "rightfulfall.com": "Leven Labs, Inc. DBA Admiral", "rigidrobin.com": "Leven Labs, Inc. DBA Admiral", "rigidveil.com": "Leven Labs, Inc. DBA Admiral", + "rigorlab.com": "Leven Labs, Inc. DBA Admiral", "ringplant.com": "Leven Labs, Inc. DBA Admiral", + "ringsrecord.com": "Leven Labs, Inc. DBA Admiral", + "ritzykey.com": "Leven Labs, Inc. DBA Admiral", + "ritzyrepresentative.com": "Leven Labs, Inc. DBA Admiral", + "ritzyveil.com": "Leven Labs, Inc. DBA Admiral", + "rockpebbles.com": "Leven Labs, Inc. DBA Admiral", "rollconnection.com": "Leven Labs, Inc. DBA Admiral", "roofrelation.com": "Leven Labs, Inc. DBA Admiral", "roseincome.com": "Leven Labs, Inc. DBA Admiral", + "rottenray.com": "Leven Labs, Inc. DBA Admiral", "ruralrobin.com": "Leven Labs, Inc. DBA Admiral", "rusticprice.com": "Leven Labs, Inc. DBA Admiral", + "ruthlessdegree.com": "Leven Labs, Inc. DBA Admiral", + "ruthlessmilk.com": "Leven Labs, Inc. DBA Admiral", + "sableloss.com": "Leven Labs, Inc. DBA Admiral", + "sablesmile.com": "Leven Labs, Inc. DBA Admiral", "sablesong.com": "Leven Labs, Inc. DBA Admiral", "sadloaf.com": "Leven Labs, Inc. DBA Admiral", + "saffronrefuge.com": "Leven Labs, Inc. DBA Admiral", + "sagargift.com": "Leven Labs, Inc. DBA Admiral", + "saltsacademy.com": "Leven Labs, Inc. DBA Admiral", "samesticks.com": "Leven Labs, Inc. DBA Admiral", "samestretch.com": "Leven Labs, Inc. DBA Admiral", "samplesamba.com": "Leven Labs, Inc. DBA Admiral", "satisfycork.com": "Leven Labs, Inc. DBA Admiral", "savoryorange.com": "Leven Labs, Inc. DBA Admiral", + "scarcecard.com": "Leven Labs, Inc. DBA Admiral", "scarceshock.com": "Leven Labs, Inc. DBA Admiral", + "scarcesign.com": "Leven Labs, Inc. DBA Admiral", "scarcestructure.com": "Leven Labs, Inc. DBA Admiral", + "scarcesurprise.com": "Leven Labs, Inc. DBA Admiral", "scaredcomfort.com": "Leven Labs, Inc. DBA Admiral", + "scaredsidewalk.com": "Leven Labs, Inc. DBA Admiral", "scaredslip.com": "Leven Labs, Inc. DBA Admiral", "scaredsnake.com": "Leven Labs, Inc. DBA Admiral", "scaredsnakes.com": "Leven Labs, Inc. DBA Admiral", "scaredsong.com": "Leven Labs, Inc. DBA Admiral", "scaredstomach.com": "Leven Labs, Inc. DBA Admiral", + "scaredswing.com": "Leven Labs, Inc. DBA Admiral", "scarefowl.com": "Leven Labs, Inc. DBA Admiral", "scarfsmash.com": "Leven Labs, Inc. DBA Admiral", + "scatteredheat.com": "Leven Labs, Inc. DBA Admiral", + "scatteredquiver.com": "Leven Labs, Inc. DBA Admiral", "scatteredstream.com": "Leven Labs, Inc. DBA Admiral", + "scenicapparel.com": "Leven Labs, Inc. DBA Admiral", "scientificshirt.com": "Leven Labs, Inc. DBA Admiral", "scintillatingscissors.com": "Leven Labs, Inc. DBA Admiral", "scintillatingsilver.com": "Leven Labs, Inc. DBA Admiral", "scissorsstatement.com": "Leven Labs, Inc. DBA Admiral", "scrapesleep.com": "Leven Labs, Inc. DBA Admiral", + "scratchsofa.com": "Leven Labs, Inc. DBA Admiral", "screechingfurniture.com": "Leven Labs, Inc. DBA Admiral", "screechingstocking.com": "Leven Labs, Inc. DBA Admiral", "screechingstove.com": "Leven Labs, Inc. DBA Admiral", "scribbleson.com": "Leven Labs, Inc. DBA Admiral", "scribblestring.com": "Leven Labs, Inc. DBA Admiral", + "scrollservice.com": "Leven Labs, Inc. DBA Admiral", + "scrubswim.com": "Leven Labs, Inc. DBA Admiral", "seashoresociety.com": "Leven Labs, Inc. DBA Admiral", "seatsmoke.com": "Leven Labs, Inc. DBA Admiral", "secondhandfall.com": "Leven Labs, Inc. DBA Admiral", + "secretivesheep.com": "Leven Labs, Inc. DBA Admiral", + "secretspiders.com": "Leven Labs, Inc. DBA Admiral", "secretturtle.com": "Leven Labs, Inc. DBA Admiral", + "seedscissors.com": "Leven Labs, Inc. DBA Admiral", "seemlysuggestion.com": "Leven Labs, Inc. DBA Admiral", "selectivesummer.com": "Leven Labs, Inc. DBA Admiral", + "selfishsea.com": "Leven Labs, Inc. DBA Admiral", "selfishsnake.com": "Leven Labs, Inc. DBA Admiral", + "sendingspire.com": "Leven Labs, Inc. DBA Admiral", + "sensorsmile.com": "Leven Labs, Inc. DBA Admiral", "separatesort.com": "Leven Labs, Inc. DBA Admiral", + "seraphichorizon.com": "Leven Labs, Inc. DBA Admiral", "seraphicjubilee.com": "Leven Labs, Inc. DBA Admiral", + "serendipityecho.com": "Leven Labs, Inc. DBA Admiral", "serenecascade.com": "Leven Labs, Inc. DBA Admiral", "serenepebble.com": "Leven Labs, Inc. DBA Admiral", "serenesurf.com": "Leven Labs, Inc. DBA Admiral", @@ -52199,23 +60889,32 @@ "serpentshampoo.com": "Leven Labs, Inc. DBA Admiral", "settleshoes.com": "Leven Labs, Inc. DBA Admiral", "shadeship.com": "Leven Labs, Inc. DBA Admiral", + "shaggytank.com": "Leven Labs, Inc. DBA Admiral", "shakegoldfish.com": "Leven Labs, Inc. DBA Admiral", "shakyseat.com": "Leven Labs, Inc. DBA Admiral", "shakysurprise.com": "Leven Labs, Inc. DBA Admiral", + "shakytaste.com": "Leven Labs, Inc. DBA Admiral", "shallowblade.com": "Leven Labs, Inc. DBA Admiral", "shamerain.com": "Leven Labs, Inc. DBA Admiral", "shapecomb.com": "Leven Labs, Inc. DBA Admiral", + "sharkskids.com": "Leven Labs, Inc. DBA Admiral", "sheargovernor.com": "Leven Labs, Inc. DBA Admiral", "shesubscriptions.com": "Leven Labs, Inc. DBA Admiral", "shinypond.com": "Leven Labs, Inc. DBA Admiral", "shirtsidewalk.com": "Leven Labs, Inc. DBA Admiral", "shiveringspot.com": "Leven Labs, Inc. DBA Admiral", "shiverscissors.com": "Leven Labs, Inc. DBA Admiral", + "shockinggrass.com": "Leven Labs, Inc. DBA Admiral", "shockingship.com": "Leven Labs, Inc. DBA Admiral", + "shredquiz.com": "Leven Labs, Inc. DBA Admiral", "shrillspoon.com": "Leven Labs, Inc. DBA Admiral", + "shydinosaurs.com": "Leven Labs, Inc. DBA Admiral", "sicksmash.com": "Leven Labs, Inc. DBA Admiral", "sierrakermit.com": "Leven Labs, Inc. DBA Admiral", + "signaturepod.com": "Leven Labs, Inc. DBA Admiral", + "siliconslow.com": "Leven Labs, Inc. DBA Admiral", "sillyscrew.com": "Leven Labs, Inc. DBA Admiral", + "simplesidewalk.com": "Leven Labs, Inc. DBA Admiral", "simulateswing.com": "Leven Labs, Inc. DBA Admiral", "sincerebuffalo.com": "Leven Labs, Inc. DBA Admiral", "sincerepelican.com": "Leven Labs, Inc. DBA Admiral", @@ -52224,69 +60923,124 @@ "sinkbooks.com": "Leven Labs, Inc. DBA Admiral", "sixauthority.com": "Leven Labs, Inc. DBA Admiral", "sixscissors.com": "Leven Labs, Inc. DBA Admiral", + "sizzlingsmoke.com": "Leven Labs, Inc. DBA Admiral", "skillfuldrop.com": "Leven Labs, Inc. DBA Admiral", "skisofa.com": "Leven Labs, Inc. DBA Admiral", + "slaysweater.com": "Leven Labs, Inc. DBA Admiral", + "slimyscarf.com": "Leven Labs, Inc. DBA Admiral", "slinksuggestion.com": "Leven Labs, Inc. DBA Admiral", "slopesoap.com": "Leven Labs, Inc. DBA Admiral", + "smallershops.com": "Leven Labs, Inc. DBA Admiral", "smashquartz.com": "Leven Labs, Inc. DBA Admiral", + "smashshoe.com": "Leven Labs, Inc. DBA Admiral", "smashsurprise.com": "Leven Labs, Inc. DBA Admiral", + "smilewound.com": "Leven Labs, Inc. DBA Admiral", + "smilingcattle.com": "Leven Labs, Inc. DBA Admiral", "smilingswim.com": "Leven Labs, Inc. DBA Admiral", + "smilingwaves.com": "Leven Labs, Inc. DBA Admiral", "smoggysnakes.com": "Leven Labs, Inc. DBA Admiral", "smoggysongs.com": "Leven Labs, Inc. DBA Admiral", + "smoggystation.com": "Leven Labs, Inc. DBA Admiral", + "snacktoken.com": "Leven Labs, Inc. DBA Admiral", + "snakemineral.com": "Leven Labs, Inc. DBA Admiral", + "snakeslang.com": "Leven Labs, Inc. DBA Admiral", "sneakwind.com": "Leven Labs, Inc. DBA Admiral", + "sneakystew.com": "Leven Labs, Inc. DBA Admiral", + "snoresmile.com": "Leven Labs, Inc. DBA Admiral", + "snowmentor.com": "Leven Labs, Inc. DBA Admiral", "soggysponge.com": "Leven Labs, Inc. DBA Admiral", "soggyzoo.com": "Leven Labs, Inc. DBA Admiral", "solarislabyrinth.com": "Leven Labs, Inc. DBA Admiral", "somberscarecrow.com": "Leven Labs, Inc. DBA Admiral", + "sombersea.com": "Leven Labs, Inc. DBA Admiral", + "sombersquirrel.com": "Leven Labs, Inc. DBA Admiral", "sombersticks.com": "Leven Labs, Inc. DBA Admiral", + "sombersurprise.com": "Leven Labs, Inc. DBA Admiral", "songsterritory.com": "Leven Labs, Inc. DBA Admiral", "soothingglade.com": "Leven Labs, Inc. DBA Admiral", + "sophisticatedstove.com": "Leven Labs, Inc. DBA Admiral", "sordidsmile.com": "Leven Labs, Inc. DBA Admiral", "soresidewalk.com": "Leven Labs, Inc. DBA Admiral", + "soresneeze.com": "Leven Labs, Inc. DBA Admiral", + "sorethunder.com": "Leven Labs, Inc. DBA Admiral", "soretrain.com": "Leven Labs, Inc. DBA Admiral", "sortsail.com": "Leven Labs, Inc. DBA Admiral", "sortsummer.com": "Leven Labs, Inc. DBA Admiral", "soundstocking.com": "Leven Labs, Inc. DBA Admiral", + "sowlettuce.com": "Leven Labs, Inc. DBA Admiral", + "spadelocket.com": "Leven Labs, Inc. DBA Admiral", + "sparkgoal.com": "Leven Labs, Inc. DBA Admiral", + "sparklingshelf.com": "Leven Labs, Inc. DBA Admiral", + "specialscissors.com": "Leven Labs, Inc. DBA Admiral", "spectacularstamp.com": "Leven Labs, Inc. DBA Admiral", "spellmist.com": "Leven Labs, Inc. DBA Admiral", "spellsalsa.com": "Leven Labs, Inc. DBA Admiral", + "spiffymachine.com": "Leven Labs, Inc. DBA Admiral", + "spirebaboon.com": "Leven Labs, Inc. DBA Admiral", "spookyexchange.com": "Leven Labs, Inc. DBA Admiral", "spookyskate.com": "Leven Labs, Inc. DBA Admiral", "spookysleet.com": "Leven Labs, Inc. DBA Admiral", + "spookystitch.com": "Leven Labs, Inc. DBA Admiral", + "spoonsilk.com": "Leven Labs, Inc. DBA Admiral", "spotlessstamp.com": "Leven Labs, Inc. DBA Admiral", "spottednoise.com": "Leven Labs, Inc. DBA Admiral", + "springolive.com": "Leven Labs, Inc. DBA Admiral", + "springsister.com": "Leven Labs, Inc. DBA Admiral", + "springsnails.com": "Leven Labs, Inc. DBA Admiral", + "sproutingbag.com": "Leven Labs, Inc. DBA Admiral", + "sprydelta.com": "Leven Labs, Inc. DBA Admiral", "sprysummit.com": "Leven Labs, Inc. DBA Admiral", "spuriousair.com": "Leven Labs, Inc. DBA Admiral", + "spuriousbase.com": "Leven Labs, Inc. DBA Admiral", + "spurioussquirrel.com": "Leven Labs, Inc. DBA Admiral", + "spuriousstranger.com": "Leven Labs, Inc. DBA Admiral", "spysubstance.com": "Leven Labs, Inc. DBA Admiral", "squalidscrew.com": "Leven Labs, Inc. DBA Admiral", + "squeakzinc.com": "Leven Labs, Inc. DBA Admiral", + "squealingturn.com": "Leven Labs, Inc. DBA Admiral", "stakingbasket.com": "Leven Labs, Inc. DBA Admiral", "stakingshock.com": "Leven Labs, Inc. DBA Admiral", "stakingsmile.com": "Leven Labs, Inc. DBA Admiral", + "staleshow.com": "Leven Labs, Inc. DBA Admiral", "stalesummer.com": "Leven Labs, Inc. DBA Admiral", + "starkscale.com": "Leven Labs, Inc. DBA Admiral", + "startingcars.com": "Leven Labs, Inc. DBA Admiral", + "statshunt.com": "Leven Labs, Inc. DBA Admiral", "statuesqueship.com": "Leven Labs, Inc. DBA Admiral", + "stayaction.com": "Leven Labs, Inc. DBA Admiral", "steadfastseat.com": "Leven Labs, Inc. DBA Admiral", "steadfastsound.com": "Leven Labs, Inc. DBA Admiral", "steadfastsystem.com": "Leven Labs, Inc. DBA Admiral", "steadycopper.com": "Leven Labs, Inc. DBA Admiral", "stealsteel.com": "Leven Labs, Inc. DBA Admiral", "steepscale.com": "Leven Labs, Inc. DBA Admiral", + "steepsister.com": "Leven Labs, Inc. DBA Admiral", "steepsquirrel.com": "Leven Labs, Inc. DBA Admiral", + "stepcattle.com": "Leven Labs, Inc. DBA Admiral", "stepplane.com": "Leven Labs, Inc. DBA Admiral", + "stepwisevideo.com": "Leven Labs, Inc. DBA Admiral", "stereoproxy.com": "Leven Labs, Inc. DBA Admiral", "stereotypedsugar.com": "Leven Labs, Inc. DBA Admiral", + "stewspiders.com": "Leven Labs, Inc. DBA Admiral", "stiffgame.com": "Leven Labs, Inc. DBA Admiral", + "stiffstem.com": "Leven Labs, Inc. DBA Admiral", "stimulatingsneeze.com": "Leven Labs, Inc. DBA Admiral", + "stingsquirrel.com": "Leven Labs, Inc. DBA Admiral", "stingycrush.com": "Leven Labs, Inc. DBA Admiral", "stingyshoe.com": "Leven Labs, Inc. DBA Admiral", "stingyspoon.com": "Leven Labs, Inc. DBA Admiral", "stockingsleet.com": "Leven Labs, Inc. DBA Admiral", + "stockingsneeze.com": "Leven Labs, Inc. DBA Admiral", "stomachscience.com": "Leven Labs, Inc. DBA Admiral", + "stonechin.com": "Leven Labs, Inc. DBA Admiral", "stopstomach.com": "Leven Labs, Inc. DBA Admiral", + "stormyachiever.com": "Leven Labs, Inc. DBA Admiral", "stormyfold.com": "Leven Labs, Inc. DBA Admiral", "straightnest.com": "Leven Labs, Inc. DBA Admiral", "strangeclocks.com": "Leven Labs, Inc. DBA Admiral", "strangersponge.com": "Leven Labs, Inc. DBA Admiral", "strangesink.com": "Leven Labs, Inc. DBA Admiral", + "streetsort.com": "Leven Labs, Inc. DBA Admiral", "stretchsister.com": "Leven Labs, Inc. DBA Admiral", "stretchsneeze.com": "Leven Labs, Inc. DBA Admiral", "stretchsquirrel.com": "Leven Labs, Inc. DBA Admiral", @@ -52297,85 +61051,149 @@ "stupendoussleet.com": "Leven Labs, Inc. DBA Admiral", "stupendoussnow.com": "Leven Labs, Inc. DBA Admiral", "stupidscene.com": "Leven Labs, Inc. DBA Admiral", + "sturdysnail.com": "Leven Labs, Inc. DBA Admiral", + "subletyoke.com": "Leven Labs, Inc. DBA Admiral", "sublimequartz.com": "Leven Labs, Inc. DBA Admiral", + "subsequentswim.com": "Leven Labs, Inc. DBA Admiral", + "substantialcarpenter.com": "Leven Labs, Inc. DBA Admiral", + "substantialgrade.com": "Leven Labs, Inc. DBA Admiral", "succeedscene.com": "Leven Labs, Inc. DBA Admiral", + "successfulscent.com": "Leven Labs, Inc. DBA Admiral", + "suddensoda.com": "Leven Labs, Inc. DBA Admiral", "sugarfriction.com": "Leven Labs, Inc. DBA Admiral", "suggestionbridge.com": "Leven Labs, Inc. DBA Admiral", "sulkycook.com": "Leven Labs, Inc. DBA Admiral", + "summerobject.com": "Leven Labs, Inc. DBA Admiral", + "sunshinegates.com": "Leven Labs, Inc. DBA Admiral", + "superchichair.com": "Leven Labs, Inc. DBA Admiral", "superficialeyes.com": "Leven Labs, Inc. DBA Admiral", "superficialspring.com": "Leven Labs, Inc. DBA Admiral", "superficialsquare.com": "Leven Labs, Inc. DBA Admiral", + "superviseshoes.com": "Leven Labs, Inc. DBA Admiral", "supportwaves.com": "Leven Labs, Inc. DBA Admiral", "suspectmark.com": "Leven Labs, Inc. DBA Admiral", "swankysquare.com": "Leven Labs, Inc. DBA Admiral", "swellstocking.com": "Leven Labs, Inc. DBA Admiral", "swelteringsleep.com": "Leven Labs, Inc. DBA Admiral", "swingslip.com": "Leven Labs, Inc. DBA Admiral", + "swordgoose.com": "Leven Labs, Inc. DBA Admiral", + "syllablesight.com": "Leven Labs, Inc. DBA Admiral", "synonymousrule.com": "Leven Labs, Inc. DBA Admiral", "synonymoussticks.com": "Leven Labs, Inc. DBA Admiral", "synthesizescarecrow.com": "Leven Labs, Inc. DBA Admiral", "tackytrains.com": "Leven Labs, Inc. DBA Admiral", + "tacojournal.com": "Leven Labs, Inc. DBA Admiral", + "talltouch.com": "Leven Labs, Inc. DBA Admiral", + "tangibleteam.com": "Leven Labs, Inc. DBA Admiral", "tangyamount.com": "Leven Labs, Inc. DBA Admiral", "tangycover.com": "Leven Labs, Inc. DBA Admiral", "tastelesstrees.com": "Leven Labs, Inc. DBA Admiral", "tastelesstrucks.com": "Leven Labs, Inc. DBA Admiral", + "tastesnake.com": "Leven Labs, Inc. DBA Admiral", + "tawdryson.com": "Leven Labs, Inc. DBA Admiral", + "tdzvm.pw": "Leven Labs, Inc. DBA Admiral", "tearfulglass.com": "Leven Labs, Inc. DBA Admiral", + "techconverter.com": "Leven Labs, Inc. DBA Admiral", + "tediousbear.com": "Leven Labs, Inc. DBA Admiral", "tediousticket.com": "Leven Labs, Inc. DBA Admiral", + "tedioustooth.com": "Leven Labs, Inc. DBA Admiral", "teenytinycellar.com": "Leven Labs, Inc. DBA Admiral", "teenytinyshirt.com": "Leven Labs, Inc. DBA Admiral", "teenytinytongue.com": "Leven Labs, Inc. DBA Admiral", + "telephoneapparatus.com": "Leven Labs, Inc. DBA Admiral", "tempertrick.com": "Leven Labs, Inc. DBA Admiral", + "tempttalk.com": "Leven Labs, Inc. DBA Admiral", "temptteam.com": "Leven Labs, Inc. DBA Admiral", "tendertest.com": "Leven Labs, Inc. DBA Admiral", "terriblethumb.com": "Leven Labs, Inc. DBA Admiral", "terrifictooth.com": "Leven Labs, Inc. DBA Admiral", + "testadmiral.com": "Leven Labs, Inc. DBA Admiral", + "texturetrick.com": "Leven Labs, Inc. DBA Admiral", + "therapeuticcars.com": "Leven Labs, Inc. DBA Admiral", + "thickticket.com": "Leven Labs, Inc. DBA Admiral", + "thicktrucks.com": "Leven Labs, Inc. DBA Admiral", + "thingsafterthought.com": "Leven Labs, Inc. DBA Admiral", "thingstaste.com": "Leven Labs, Inc. DBA Admiral", "thinkitten.com": "Leven Labs, Inc. DBA Admiral", + "thinkitwice.com": "Leven Labs, Inc. DBA Admiral", "thirdrespect.com": "Leven Labs, Inc. DBA Admiral", + "thirstytwig.com": "Leven Labs, Inc. DBA Admiral", "thomastorch.com": "Leven Labs, Inc. DBA Admiral", "thoughtlessknot.com": "Leven Labs, Inc. DBA Admiral", "threetruck.com": "Leven Labs, Inc. DBA Admiral", "thrivingmarketplace.com": "Leven Labs, Inc. DBA Admiral", "ticketaunt.com": "Leven Labs, Inc. DBA Admiral", + "ticklesign.com": "Leven Labs, Inc. DBA Admiral", "tidymitten.com": "Leven Labs, Inc. DBA Admiral", + "tightpowder.com": "Leven Labs, Inc. DBA Admiral", + "tinyswans.com": "Leven Labs, Inc. DBA Admiral", + "tinytendency.com": "Leven Labs, Inc. DBA Admiral", "tiredthroat.com": "Leven Labs, Inc. DBA Admiral", "tiresomethunder.com": "Leven Labs, Inc. DBA Admiral", + "toolcapital.com": "Leven Labs, Inc. DBA Admiral", + "toomanyalts.com": "Leven Labs, Inc. DBA Admiral", + "torpidtongue.com": "Leven Labs, Inc. DBA Admiral", + "trackcaddie.com": "Leven Labs, Inc. DBA Admiral", "tradetooth.com": "Leven Labs, Inc. DBA Admiral", + "trafficviews.com": "Leven Labs, Inc. DBA Admiral", + "tranquilamulet.com": "Leven Labs, Inc. DBA Admiral", + "tranquilarchipelago.com": "Leven Labs, Inc. DBA Admiral", "tranquilcan.com": "Leven Labs, Inc. DBA Admiral", "tranquilcanyon.com": "Leven Labs, Inc. DBA Admiral", "tranquilplume.com": "Leven Labs, Inc. DBA Admiral", + "tranquilside.com": "Leven Labs, Inc. DBA Admiral", "tranquilveil.com": "Leven Labs, Inc. DBA Admiral", "tranquilveranda.com": "Leven Labs, Inc. DBA Admiral", + "trappush.com": "Leven Labs, Inc. DBA Admiral", + "treadbun.com": "Leven Labs, Inc. DBA Admiral", "tremendousearthquake.com": "Leven Labs, Inc. DBA Admiral", "tremendousplastic.com": "Leven Labs, Inc. DBA Admiral", + "tremendoustime.com": "Leven Labs, Inc. DBA Admiral", "tritebadge.com": "Leven Labs, Inc. DBA Admiral", "tritethunder.com": "Leven Labs, Inc. DBA Admiral", + "tritetongue.com": "Leven Labs, Inc. DBA Admiral", "troubledtail.com": "Leven Labs, Inc. DBA Admiral", "troubleshade.com": "Leven Labs, Inc. DBA Admiral", + "truckstomatoes.com": "Leven Labs, Inc. DBA Admiral", "truculentrate.com": "Leven Labs, Inc. DBA Admiral", "tumbleicicle.com": "Leven Labs, Inc. DBA Admiral", + "tuneupcoffee.com": "Leven Labs, Inc. DBA Admiral", + "twistloss.com": "Leven Labs, Inc. DBA Admiral", + "twistsweater.com": "Leven Labs, Inc. DBA Admiral", "typicalairplane.com": "Leven Labs, Inc. DBA Admiral", "typicalteeth.com": "Leven Labs, Inc. DBA Admiral", + "tzwaw.pw": "Leven Labs, Inc. DBA Admiral", "ubiquitoussea.com": "Leven Labs, Inc. DBA Admiral", "ubiquitousyard.com": "Leven Labs, Inc. DBA Admiral", "ultraoranges.com": "Leven Labs, Inc. DBA Admiral", + "ultravalid.com": "Leven Labs, Inc. DBA Admiral", "unablehope.com": "Leven Labs, Inc. DBA Admiral", + "unaccountablecreator.com": "Leven Labs, Inc. DBA Admiral", "unaccountablepie.com": "Leven Labs, Inc. DBA Admiral", + "unarmedindustry.com": "Leven Labs, Inc. DBA Admiral", "unbecominghall.com": "Leven Labs, Inc. DBA Admiral", "unbecominglamp.com": "Leven Labs, Inc. DBA Admiral", "uncoveredexpert.com": "Leven Labs, Inc. DBA Admiral", + "understoodocean.com": "Leven Labs, Inc. DBA Admiral", "unequalbrake.com": "Leven Labs, Inc. DBA Admiral", "unequaltrail.com": "Leven Labs, Inc. DBA Admiral", "uninterestedquarter.com": "Leven Labs, Inc. DBA Admiral", + "unknowncontrol.com": "Leven Labs, Inc. DBA Admiral", "unknowncrate.com": "Leven Labs, Inc. DBA Admiral", + "unknowntray.com": "Leven Labs, Inc. DBA Admiral", + "untidyquestion.com": "Leven Labs, Inc. DBA Admiral", "untidyrice.com": "Leven Labs, Inc. DBA Admiral", "unusedstone.com": "Leven Labs, Inc. DBA Admiral", + "unusualtitle.com": "Leven Labs, Inc. DBA Admiral", "unwieldyhealth.com": "Leven Labs, Inc. DBA Admiral", "unwieldyimpulse.com": "Leven Labs, Inc. DBA Admiral", "unwieldyplastic.com": "Leven Labs, Inc. DBA Admiral", "uppitytime.com": "Leven Labs, Inc. DBA Admiral", "uselesslumber.com": "Leven Labs, Inc. DBA Admiral", + "validmemo.com": "Leven Labs, Inc. DBA Admiral", + "vanfireworks.com": "Leven Labs, Inc. DBA Admiral", "vanishmemory.com": "Leven Labs, Inc. DBA Admiral", + "velvetnova.com": "Leven Labs, Inc. DBA Admiral", "velvetquasar.com": "Leven Labs, Inc. DBA Admiral", "vengefulgrass.com": "Leven Labs, Inc. DBA Admiral", "venomousvessel.com": "Leven Labs, Inc. DBA Admiral", @@ -52383,44 +61201,79 @@ "verdantanswer.com": "Leven Labs, Inc. DBA Admiral", "verdantlabyrinth.com": "Leven Labs, Inc. DBA Admiral", "verdantloom.com": "Leven Labs, Inc. DBA Admiral", + "verdantsculpture.com": "Leven Labs, Inc. DBA Admiral", "verseballs.com": "Leven Labs, Inc. DBA Admiral", "vibrantcelebration.com": "Leven Labs, Inc. DBA Admiral", "vibrantgale.com": "Leven Labs, Inc. DBA Admiral", "vibranthaven.com": "Leven Labs, Inc. DBA Admiral", "vibrantpact.com": "Leven Labs, Inc. DBA Admiral", + "vibrantsundown.com": "Leven Labs, Inc. DBA Admiral", "vibranttalisman.com": "Leven Labs, Inc. DBA Admiral", "vibrantvale.com": "Leven Labs, Inc. DBA Admiral", + "victoriousrequest.com": "Leven Labs, Inc. DBA Admiral", "virtualvincent.com": "Leven Labs, Inc. DBA Admiral", "vividcanopy.com": "Leven Labs, Inc. DBA Admiral", "vividfrost.com": "Leven Labs, Inc. DBA Admiral", "vividmeadow.com": "Leven Labs, Inc. DBA Admiral", "vividplume.com": "Leven Labs, Inc. DBA Admiral", + "voicelessvein.com": "Leven Labs, Inc. DBA Admiral", + "voidgoo.com": "Leven Labs, Inc. DBA Admiral", "volatileprofit.com": "Leven Labs, Inc. DBA Admiral", "volatilevessel.com": "Leven Labs, Inc. DBA Admiral", "voraciousgrip.com": "Leven Labs, Inc. DBA Admiral", + "vq1qi.pw": "Leven Labs, Inc. DBA Admiral", + "waitingnumber.com": "Leven Labs, Inc. DBA Admiral", "wantingwindow.com": "Leven Labs, Inc. DBA Admiral", "warmafterthought.com": "Leven Labs, Inc. DBA Admiral", "warmquiver.com": "Leven Labs, Inc. DBA Admiral", + "warnwing.com": "Leven Labs, Inc. DBA Admiral", + "washbanana.com": "Leven Labs, Inc. DBA Admiral", + "wateryvan.com": "Leven Labs, Inc. DBA Admiral", + "waterywave.com": "Leven Labs, Inc. DBA Admiral", + "waterywrist.com": "Leven Labs, Inc. DBA Admiral", "wearbasin.com": "Leven Labs, Inc. DBA Admiral", + "websitesdude.com": "Leven Labs, Inc. DBA Admiral", + "wellgroomedapparel.com": "Leven Labs, Inc. DBA Admiral", "wellgroomedhydrant.com": "Leven Labs, Inc. DBA Admiral", + "wellmadefrog.com": "Leven Labs, Inc. DBA Admiral", + "westpalmweb.com": "Leven Labs, Inc. DBA Admiral", "whimsicalcanyon.com": "Leven Labs, Inc. DBA Admiral", "whimsicalgrove.com": "Leven Labs, Inc. DBA Admiral", + "whineattempt.com": "Leven Labs, Inc. DBA Admiral", + "whirlwealth.com": "Leven Labs, Inc. DBA Admiral", + "whiskyqueue.com": "Leven Labs, Inc. DBA Admiral", "whisperingcascade.com": "Leven Labs, Inc. DBA Admiral", + "whisperingcrib.com": "Leven Labs, Inc. DBA Admiral", "whisperingquasar.com": "Leven Labs, Inc. DBA Admiral", "whisperingsummit.com": "Leven Labs, Inc. DBA Admiral", "whispermeeting.com": "Leven Labs, Inc. DBA Admiral", "wildcommittee.com": "Leven Labs, Inc. DBA Admiral", + "wirecomic.com": "Leven Labs, Inc. DBA Admiral", + "wiredforcoffee.com": "Leven Labs, Inc. DBA Admiral", + "wirypaste.com": "Leven Labs, Inc. DBA Admiral", "wistfulwaste.com": "Leven Labs, Inc. DBA Admiral", + "wittypopcorn.com": "Leven Labs, Inc. DBA Admiral", "wittyshack.com": "Leven Labs, Inc. DBA Admiral", "workoperation.com": "Leven Labs, Inc. DBA Admiral", + "worldlever.com": "Leven Labs, Inc. DBA Admiral", + "worriednumber.com": "Leven Labs, Inc. DBA Admiral", + "worriedwine.com": "Leven Labs, Inc. DBA Admiral", "wretchedfloor.com": "Leven Labs, Inc. DBA Admiral", + "wrongpotato.com": "Leven Labs, Inc. DBA Admiral", "wrongwound.com": "Leven Labs, Inc. DBA Admiral", + "wtaccesscontrol.com": "Leven Labs, Inc. DBA Admiral", + "xovq5nemr.com": "Leven Labs, Inc. DBA Admiral", + "yieldingwoman.com": "Leven Labs, Inc. DBA Admiral", + "zbwp6ghm.com": "Leven Labs, Inc. DBA Admiral", + "zephyrcatalyst.com": "Leven Labs, Inc. DBA Admiral", "zephyrlabyrinth.com": "Leven Labs, Inc. DBA Admiral", "zestycrime.com": "Leven Labs, Inc. DBA Admiral", "zestyhorizon.com": "Leven Labs, Inc. DBA Admiral", "zestyrover.com": "Leven Labs, Inc. DBA Admiral", + "zestywire.com": "Leven Labs, Inc. DBA Admiral", "zipperxray.com": "Leven Labs, Inc. DBA Admiral", "zlp6s.pw": "Leven Labs, Inc. DBA Admiral", + "zonewedgeshaft.com": "Leven Labs, Inc. DBA Admiral", "abtasty.com": "AB Tasty", "flagship.io": "AB Tasty", "acexedge.com": "Human Security, Inc.", From bbf31c455696654adbe6a92c35b6f4e8c0ed747f Mon Sep 17 00:00:00 2001 From: Dax the Duck Date: Mon, 5 Aug 2024 13:06:11 +0000 Subject: [PATCH 12/32] Set marketing version to 1.101.0 --- Configuration/Version.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/Version.xcconfig b/Configuration/Version.xcconfig index f74ff7935d2..ced03aa328b 100644 --- a/Configuration/Version.xcconfig +++ b/Configuration/Version.xcconfig @@ -1 +1 @@ -MARKETING_VERSION = 1.100.0 +MARKETING_VERSION = 1.101.0 From 1adbf8fd83034d8d36fc5681ffb4baa95ccb70c9 Mon Sep 17 00:00:00 2001 From: Dax the Duck Date: Mon, 5 Aug 2024 13:21:35 +0000 Subject: [PATCH 13/32] Bump version to 1.101.0 (239) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index 773f6594824..d3ff8937a6a 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 238 +CURRENT_PROJECT_VERSION = 239 From 43329ec6f720a5472f20899ed190bf29948da6ca Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Aug 2024 17:21:05 +0200 Subject: [PATCH 14/32] Bump Submodules/privacy-reference-tests from `a603ff9` to `afb4f61` (#3046) Dependabot PR: https://github.com/duckduckgo/macos-browser/pull/3046 --- Submodules/privacy-reference-tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Submodules/privacy-reference-tests b/Submodules/privacy-reference-tests index a603ff9af22..afb4f6128a3 160000 --- a/Submodules/privacy-reference-tests +++ b/Submodules/privacy-reference-tests @@ -1 +1 @@ -Subproject commit a603ff9af22ca3ff7ce2e7ffbfe18c447d9f23e8 +Subproject commit afb4f6128a3b50d53ddcb1897ea1fb4df6858aa1 From 4ca12bf19f066e92eeb6ae63b22a6a1b496e3f4a Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Mon, 5 Aug 2024 17:40:04 +0100 Subject: [PATCH 15/32] fixed platform.name (#3072) Task/Issue URL: https://app.asana.com/0/1204099484721401/1207978998644880/f --- DuckDuckGo/YoutubePlayer/DuckPlayer.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DuckDuckGo/YoutubePlayer/DuckPlayer.swift b/DuckDuckGo/YoutubePlayer/DuckPlayer.swift index edfb674c87e..4fb257e3abc 100644 --- a/DuckDuckGo/YoutubePlayer/DuckPlayer.swift +++ b/DuckDuckGo/YoutubePlayer/DuckPlayer.swift @@ -258,7 +258,7 @@ final class DuckPlayer { let pip = InitialPlayerSettings.PIP(state: isPiPEnabled ? .enabled : .disabled) let autoplay = InitialPlayerSettings.Autoplay(state: isAutoplayEnabled ? .enabled : .disabled) - let platform = InitialPlayerSettings.Platform(name: "ios") + let platform = InitialPlayerSettings.Platform(name: "macos") let environment = InitialPlayerSettings.Environment.development let locale = InitialPlayerSettings.Locale.en let playerSettings = InitialPlayerSettings.PlayerSettings(pip: pip, autoplay: autoplay) From 879b969fc280fec12634166583351642d090c2ce Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Mon, 5 Aug 2024 23:57:35 +0200 Subject: [PATCH 16/32] VPN Domain exclusions (internal release) (#3045) Task/Issue URL: https://app.asana.com/0/0/1207936340790549/f BSK PR: https://github.com/duckduckgo/BrowserServicesKit/pull/918 iOS PR: https://github.com/duckduckgo/iOS/pull/3164 ## Description Implements domain exclusions for internal users only. --- DuckDuckGo.xcodeproj/project.pbxproj | 70 ++++++- .../xcshareddata/swiftpm/Package.resolved | 4 +- ...kDuckGo Privacy Browser App Store.xcscheme | 6 + .../DuckDuckGo Privacy Browser.xcscheme | 6 + DuckDuckGo/Application/URLEventHandler.swift | 39 +--- .../UserText+NetworkProtection.swift | 12 ++ DuckDuckGo/Localizable.xcstrings | 3 + .../View/NavigationBarPopovers.swift | 20 +- .../ActiveDomainPublisher.swift | 100 ++++++++++ .../NetworkProtectionDebugMenu.swift | 24 ++- .../NetworkProtectionDebugUtilities.swift | 4 + ...etworkProtectionNavBarPopoverManager.swift | 66 +++++-- .../NetworkProtectionTunnelController.swift | 7 - .../SiteTroubleshootingInfoPublisher.swift | 111 +++++++++++ .../BothAppTargets/VPNUIActionHandler.swift | 65 ++++++ .../BothAppTargets/VPNURLEventHandler.swift | 91 +++++++++ .../AddExcludedDomainButtonsView.swift | 187 ++++++++++++++++++ .../AddExcludedDomainView.swift | 112 +++++++++++ .../ExcludedDomains.storyboard | 187 ++++++++++++++++++ .../ExcludedDomainsModel.swift | 54 +++++ .../ExcludedDomainsViewController.swift | 178 +++++++++++++++++ .../Model/VPNPreferencesModel.swift | 47 ++++- .../Preferences/View/PreferencesVPNView.swift | 19 +- .../Tab/View/BrowserTabViewController.swift | 2 +- .../View/WindowControllersManager.swift | 8 +- DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift | 7 +- .../TunnelControllerIPCService.swift | 3 + DuckDuckGoVPN/VPNUIActionHandler.swift | 58 ++++++ .../DataBrokerProtection/Package.swift | 2 +- .../NetworkProtectionMac/Package.swift | 2 +- .../FlowManagers/TCPFlowManager.swift | 22 ++- .../TransparentProxyAppMessageHandler.swift | 12 +- .../Settings/TransparentProxySettings.swift | 38 +++- .../TransparentProxyProvider.swift | 159 +++++++++------ .../Animation/AnimationConstants.swift | 23 +++ .../Menu/StatusBarMenu.swift | 45 +++-- .../NetworkProtectionAsset.swift | 3 + .../NetworkProtectionPopover.swift | 49 ++--- .../Icons/Check-16D.imageset/Check-16D.pdf | Bin 0 -> 1525 bytes .../Icons/Check-16D.imageset/Contents.json | 15 ++ .../SwiftUI/AccordionView.swift | 119 +++++++++++ .../SwiftUI/MenuItemButton.swift | 2 +- .../SwiftUI/MenuItemCustomButton.swift | 2 +- .../VPNUIActionHandling.swift} | 5 +- .../DebugInformationView.swift | 24 +-- .../DebugInformationViewModel.swift | 12 +- .../SiteTroubleshootingInfo.swift} | 28 ++- .../SiteTroubleshootingView.swift | 97 +++++++++ .../SiteTroubleshootingViewModel.swift | 88 +++++++++ .../NetworkProtectionStatusView.swift | 14 +- .../NetworkProtectionStatusViewModel.swift | 25 +-- .../TunnelControllerView.swift | 10 + .../TunnelControllerViewModel.swift | 12 +- .../MockVPNUIActionHandler.swift | 5 +- .../NetworkProtectionAssetTests.swift | 3 +- LocalPackages/SubscriptionUI/Package.swift | 2 +- .../View/NavigationBarPopoversTests.swift | 1 + 57 files changed, 2046 insertions(+), 263 deletions(-) create mode 100644 DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/ActiveDomainPublisher.swift create mode 100644 DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/SiteTroubleshootingInfoPublisher.swift create mode 100644 DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNUIActionHandler.swift create mode 100644 DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNURLEventHandler.swift create mode 100644 DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainButtonsView.swift create mode 100644 DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainView.swift create mode 100644 DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomains.storyboard create mode 100644 DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsModel.swift create mode 100644 DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsViewController.swift create mode 100644 DuckDuckGoVPN/VPNUIActionHandler.swift create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Animation/AnimationConstants.swift create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Check-16D.pdf create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Contents.json create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/AccordionView.swift rename LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/{VPNUIActionHandler/VPNUIActionHandler.swift => VPNUIActionHandling/VPNUIActionHandling.swift} (84%) rename LocalPackages/NetworkProtectionMac/Sources/{VPNAppLauncher/AppLauncher+VPNUIActionHandler.swift => NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingInfo.swift} (50%) create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingView.swift create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingViewModel.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 4c86d42ff33..8498cca34f6 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -1576,11 +1576,27 @@ 7B4D8A222BDA857300852966 /* VPNOperationErrorRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4D8A202BDA857300852966 /* VPNOperationErrorRecorder.swift */; }; 7B4D8A232BDA857300852966 /* VPNOperationErrorRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4D8A202BDA857300852966 /* VPNOperationErrorRecorder.swift */; }; 7B4D8A242BDA857300852966 /* VPNOperationErrorRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4D8A202BDA857300852966 /* VPNOperationErrorRecorder.swift */; }; + 7B5A23682C468233007213AC /* ExcludedDomainsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5A23672C468233007213AC /* ExcludedDomainsViewController.swift */; }; + 7B5A23692C468233007213AC /* ExcludedDomainsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5A23672C468233007213AC /* ExcludedDomainsViewController.swift */; }; + 7B5A236F2C46A116007213AC /* ExcludedDomainsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5A236E2C46A116007213AC /* ExcludedDomainsModel.swift */; }; + 7B5A23702C46A116007213AC /* ExcludedDomainsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5A236E2C46A116007213AC /* ExcludedDomainsModel.swift */; }; + 7B5A23752C46A4A8007213AC /* ExcludedDomains.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7B5A23742C46A4A8007213AC /* ExcludedDomains.storyboard */; }; + 7B5A23762C46A4A8007213AC /* ExcludedDomains.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7B5A23742C46A4A8007213AC /* ExcludedDomains.storyboard */; }; + 7B60AFFA2C511B65008E32A3 /* VPNUIActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60AFF92C511B65008E32A3 /* VPNUIActionHandler.swift */; }; + 7B60AFFB2C511C68008E32A3 /* VPNUIActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60AFF92C511B65008E32A3 /* VPNUIActionHandler.swift */; }; + 7B60AFFE2C514269008E32A3 /* VPNURLEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60AFFC2C514260008E32A3 /* VPNURLEventHandler.swift */; }; + 7B60AFFF2C51426A008E32A3 /* VPNURLEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60AFFC2C514260008E32A3 /* VPNURLEventHandler.swift */; }; + 7B60B0022C5145EC008E32A3 /* VPNUIActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60B0002C514541008E32A3 /* VPNUIActionHandler.swift */; }; + 7B60B0032C5145ED008E32A3 /* VPNUIActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60B0002C514541008E32A3 /* VPNUIActionHandler.swift */; }; 7B624F172BA25C1F00A6C544 /* NetworkProtectionUI in Frameworks */ = {isa = PBXBuildFile; productRef = 7B624F162BA25C1F00A6C544 /* NetworkProtectionUI */; }; 7B6545ED2C0778BB00115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6545EC2C0778BB00115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift */; }; 7B6545EE2C0779D500115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6545EC2C0778BB00115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift */; }; 7B7DFB202B7E736B009EA1A3 /* MacPacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEF12E6D2A2111880023E6BF /* MacPacketTunnelProvider.swift */; }; 7B7DFB222B7E7473009EA1A3 /* Networking in Frameworks */ = {isa = PBXBuildFile; productRef = 7B7DFB212B7E7473009EA1A3 /* Networking */; }; + 7B7F5D212C526CE600826256 /* AddExcludedDomainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7F5D202C526CE600826256 /* AddExcludedDomainView.swift */; }; + 7B7F5D222C526CE600826256 /* AddExcludedDomainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7F5D202C526CE600826256 /* AddExcludedDomainView.swift */; }; + 7B7F5D242C52725A00826256 /* AddExcludedDomainButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7F5D232C52725A00826256 /* AddExcludedDomainButtonsView.swift */; }; + 7B7F5D252C52725A00826256 /* AddExcludedDomainButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7F5D232C52725A00826256 /* AddExcludedDomainButtonsView.swift */; }; 7B7FCD0F2BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7FCD0E2BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift */; }; 7B7FCD102BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7FCD0E2BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift */; }; 7B8594192B5B26230007EB3E /* UDSHelper in Frameworks */ = {isa = PBXBuildFile; productRef = 7B8594182B5B26230007EB3E /* UDSHelper */; }; @@ -1622,6 +1638,10 @@ 7BAF9E4C2A8A3CCA002D3B6E /* UserDefaults+NetworkProtectionShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B934C402A866DD400FC8F9C /* UserDefaults+NetworkProtectionShared.swift */; }; 7BAF9E4D2A8A3CCB002D3B6E /* UserDefaults+NetworkProtectionShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B934C402A866DD400FC8F9C /* UserDefaults+NetworkProtectionShared.swift */; }; 7BB108592A43375D000AB95F /* PFMoveApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BB108582A43375D000AB95F /* PFMoveApplication.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7BB4BC632C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB4BC622C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift */; }; + 7BB4BC642C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB4BC622C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift */; }; + 7BB4BC6A2C5CD96200E06FC8 /* ActiveDomainPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB4BC692C5CD96200E06FC8 /* ActiveDomainPublisher.swift */; }; + 7BB4BC6B2C5CD96200E06FC8 /* ActiveDomainPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB4BC692C5CD96200E06FC8 /* ActiveDomainPublisher.swift */; }; 7BBD45B12A691AB500C83CA9 /* NetworkProtectionDebugUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBD45B02A691AB500C83CA9 /* NetworkProtectionDebugUtilities.swift */; }; 7BBD45B22A691AB500C83CA9 /* NetworkProtectionDebugUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBD45B02A691AB500C83CA9 /* NetworkProtectionDebugUtilities.swift */; }; 7BBE2B7B2B61663C00697445 /* NetworkProtectionProxy in Frameworks */ = {isa = PBXBuildFile; productRef = 7BBE2B7A2B61663C00697445 /* NetworkProtectionProxy */; }; @@ -3512,10 +3532,18 @@ 7B4D8A202BDA857300852966 /* VPNOperationErrorRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNOperationErrorRecorder.swift; sourceTree = ""; }; 7B5291882A1697680022E406 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 7B5291892A169BC90022E406 /* DeveloperID.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DeveloperID.xcconfig; sourceTree = ""; }; + 7B5A23672C468233007213AC /* ExcludedDomainsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExcludedDomainsViewController.swift; sourceTree = ""; }; + 7B5A236E2C46A116007213AC /* ExcludedDomainsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExcludedDomainsModel.swift; sourceTree = ""; }; + 7B5A23742C46A4A8007213AC /* ExcludedDomains.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = ExcludedDomains.storyboard; sourceTree = ""; }; + 7B60AFF92C511B65008E32A3 /* VPNUIActionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNUIActionHandler.swift; sourceTree = ""; }; + 7B60AFFC2C514260008E32A3 /* VPNURLEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNURLEventHandler.swift; sourceTree = ""; }; + 7B60B0002C514541008E32A3 /* VPNUIActionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNUIActionHandler.swift; sourceTree = ""; }; 7B6545EC2C0778BB00115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VPNControllerUDSClient+ConvenienceInitializers.swift"; sourceTree = ""; }; 7B6EC5E42AE2D8AF004FE6DF /* DuckDuckGoDBPAgentAppStore.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DuckDuckGoDBPAgentAppStore.xcconfig; sourceTree = ""; }; 7B6EC5E52AE2D8AF004FE6DF /* DuckDuckGoDBPAgent.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DuckDuckGoDBPAgent.xcconfig; sourceTree = ""; }; 7B76E6852AD5D77600186A84 /* XPCHelper */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = XPCHelper; sourceTree = ""; }; + 7B7F5D202C526CE600826256 /* AddExcludedDomainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddExcludedDomainView.swift; sourceTree = ""; }; + 7B7F5D232C52725A00826256 /* AddExcludedDomainButtonsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddExcludedDomainButtonsView.swift; sourceTree = ""; }; 7B7FCD0E2BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+vpnLegacyUser.swift"; sourceTree = ""; }; 7B8594172B5B25FB0007EB3E /* UDSHelper */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = UDSHelper; sourceTree = ""; }; 7B8DB3192B504D7500EC16DA /* VPNAppEventsHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNAppEventsHandler.swift; sourceTree = ""; }; @@ -3537,6 +3565,8 @@ 7BA7CC4D2AD11F6F0042E5CE /* NetworkProtectionIPCTunnelController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkProtectionIPCTunnelController.swift; sourceTree = ""; }; 7BB108572A43375D000AB95F /* PFMoveApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFMoveApplication.h; sourceTree = ""; }; 7BB108582A43375D000AB95F /* PFMoveApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFMoveApplication.m; sourceTree = ""; }; + 7BB4BC622C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteTroubleshootingInfoPublisher.swift; sourceTree = ""; }; + 7BB4BC692C5CD96200E06FC8 /* ActiveDomainPublisher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActiveDomainPublisher.swift; sourceTree = ""; }; 7BBD45B02A691AB500C83CA9 /* NetworkProtectionDebugUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionDebugUtilities.swift; sourceTree = ""; }; 7BCB90C12C18626E008E3543 /* VPNControllerXPCClient+ConvenienceInitializers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VPNControllerXPCClient+ConvenienceInitializers.swift"; sourceTree = ""; }; 7BD1688D2AD4A4C400D24876 /* NetworkExtensionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkExtensionController.swift; sourceTree = ""; }; @@ -5324,6 +5354,7 @@ 4B4D60572A0B29FA00BCD287 /* AppAndExtensionTargets */, 4B4D60602A0B29FA00BCD287 /* AppTargets */, 4B4D60742A0B29FA00BCD287 /* NetworkExtensionTargets */, + 7B5A236D2C46A0DA007213AC /* ExcludedDomains */, ); path = NetworkProtection; sourceTree = ""; @@ -5367,6 +5398,8 @@ 4B4D60632A0B29FA00BCD287 /* BothAppTargets */ = { isa = PBXGroup; children = ( + 7BB4BC692C5CD96200E06FC8 /* ActiveDomainPublisher.swift */, + 7BB4BC622C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift */, 4B4D60722A0B29FA00BCD287 /* EventMapping+NetworkProtectionError.swift */, BDE981DB2BBD110800645880 /* Assets */, 7BD3AF5C2A8E7AF1006F9F56 /* KeychainType+ClientDefault.swift */, @@ -5388,6 +5421,8 @@ 7B934C3D2A866CFF00FC8F9C /* NetworkProtectionOnboardingMenu.swift */, B6F1B02D2BCE6B47005E863C /* TunnelControllerProvider.swift */, 4BE3A6C02C16BEB1003FC378 /* VPNRedditSessionWorkaround.swift */, + 7B60B0002C514541008E32A3 /* VPNUIActionHandler.swift */, + 7B60AFFC2C514260008E32A3 /* VPNURLEventHandler.swift */, ); path = BothAppTargets; sourceTree = ""; @@ -6108,6 +6143,18 @@ path = UITests; sourceTree = ""; }; + 7B5A236D2C46A0DA007213AC /* ExcludedDomains */ = { + isa = PBXGroup; + children = ( + 7B5A23742C46A4A8007213AC /* ExcludedDomains.storyboard */, + 7B5A23672C468233007213AC /* ExcludedDomainsViewController.swift */, + 7B5A236E2C46A116007213AC /* ExcludedDomainsModel.swift */, + 7B7F5D202C526CE600826256 /* AddExcludedDomainView.swift */, + 7B7F5D232C52725A00826256 /* AddExcludedDomainButtonsView.swift */, + ); + path = ExcludedDomains; + sourceTree = ""; + }; 7B6EC5E32AE2D88C004FE6DF /* DBP */ = { isa = PBXGroup; children = ( @@ -6129,6 +6176,7 @@ isa = PBXGroup; children = ( 7BA7CC132AD11DC80042E5CE /* AppLauncher+DefaultInitializer.swift */, + 7B60AFF92C511B65008E32A3 /* VPNUIActionHandler.swift */, 7BA7CC0E2AD11DC80042E5CE /* DuckDuckGoVPNAppDelegate.swift */, 7BD1688D2AD4A4C400D24876 /* NetworkExtensionController.swift */, EEDE50102BA360C80017F3C4 /* NetworkProtection+VPNAgentConvenienceInitializers.swift */, @@ -9240,6 +9288,7 @@ 3706FCD0293F65D500E42796 /* BookmarksBarCollectionViewItem.xib in Resources */, 3706FCD2293F65D500E42796 /* shield.json in Resources */, 3706FCD4293F65D500E42796 /* TabBarViewItem.xib in Resources */, + 7B5A23762C46A4A8007213AC /* ExcludedDomains.storyboard in Resources */, 3706FCD6293F65D500E42796 /* httpsMobileV2FalsePositives.json in Resources */, 3706FCD8293F65D500E42796 /* BookmarksBar.storyboard in Resources */, 3706FCD9293F65D500E42796 /* trackers-1.json in Resources */, @@ -9432,6 +9481,7 @@ 4BE5336B286912D40019DBFD /* BookmarksBarCollectionViewItem.xib in Resources */, AA34396C2754D4E300B241FA /* shield.json in Resources */, AA7412B324D0B3AC00D22FE0 /* TabBarViewItem.xib in Resources */, + 7B5A23752C46A4A8007213AC /* ExcludedDomains.storyboard in Resources */, 4B677435255DBEB800025BD8 /* httpsMobileV2FalsePositives.json in Resources */, 4BD18F05283F151F00058124 /* BookmarksBar.storyboard in Resources */, AA3439792754D55100B241FA /* trackers-1.json in Resources */, @@ -9875,6 +9925,7 @@ 3706FAAD293F65D500E42796 /* BadgeNotificationAnimationModel.swift in Sources */, 3706FAAE293F65D500E42796 /* HyperLink.swift in Sources */, 3706FAAF293F65D500E42796 /* PasteboardWriting.swift in Sources */, + 7B5A23692C468233007213AC /* ExcludedDomainsViewController.swift in Sources */, B6E3E5512BBFCDEE00A41922 /* OpenDownloadsCellView.swift in Sources */, 3706FAB0293F65D500E42796 /* BookmarkOutlineCellView.swift in Sources */, 3706FAB1293F65D500E42796 /* UnprotectedDomains.xcdatamodeld in Sources */, @@ -10208,6 +10259,7 @@ 3706FB93293F65D500E42796 /* PasteboardFolder.swift in Sources */, 3706FB94293F65D500E42796 /* CookieManagedNotificationView.swift in Sources */, EEC4A65F2B277EE100F7C0AA /* VPNLocationViewModel.swift in Sources */, + 7B60B0032C5145ED008E32A3 /* VPNUIActionHandler.swift in Sources */, 370A34B22AB24E3700C77F7C /* SyncDebugMenu.swift in Sources */, 4B4D60BE2A0C848A00BCD287 /* NetworkProtection+ConvenienceInitializers.swift in Sources */, 3706FB95293F65D500E42796 /* PermissionType.swift in Sources */, @@ -10270,6 +10322,7 @@ 3706FBBC293F65D500E42796 /* NSViewExtension.swift in Sources */, 3706FBBE293F65D500E42796 /* DownloadListViewModel.swift in Sources */, 3706FBBF293F65D500E42796 /* BookmarkManagementDetailViewController.swift in Sources */, + 7BB4BC642C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift in Sources */, B6B4D1CB2B0C8C9200C26286 /* FirefoxCompatibilityPreferences.swift in Sources */, F188268E2BBF01C400D9AC4F /* PixelDataModel.xcdatamodeld in Sources */, 3706FBC0293F65D500E42796 /* CSVImporter.swift in Sources */, @@ -10355,6 +10408,7 @@ 9F56CFAE2B84326C00BB7F11 /* AddEditBookmarkDialogViewModel.swift in Sources */, 3706FBF3293F65D500E42796 /* PseudoFolder.swift in Sources */, 1D26EBAD2B74BECB0002A93F /* NSImageSendable.swift in Sources */, + 7B7F5D252C52725A00826256 /* AddExcludedDomainButtonsView.swift in Sources */, 1D220BFD2B87AACF00F8BBC6 /* PrivacyProtectionStatus.swift in Sources */, 3706FBF8293F65D500E42796 /* TabBarFooter.swift in Sources */, B626A7612992407D00053070 /* CancellableExtension.swift in Sources */, @@ -10505,6 +10559,7 @@ 3706FC53293F65D500E42796 /* TabBarScrollView.swift in Sources */, B6104E9C2BA9C173008636B2 /* DownloadResumeData.swift in Sources */, 3706FC54293F65D500E42796 /* BookmarkListTreeControllerDataSource.swift in Sources */, + 7B7F5D222C526CE600826256 /* AddExcludedDomainView.swift in Sources */, 3706FC55293F65D500E42796 /* AddressBarViewController.swift in Sources */, 3706FC56293F65D500E42796 /* Permissions.swift in Sources */, 9F872D992B8DA9F800138637 /* Bookmarks+Tab.swift in Sources */, @@ -10537,6 +10592,7 @@ 7B6545EE2C0779D500115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift in Sources */, B6F9BDE52B45CD1900677B33 /* ModalView.swift in Sources */, 9F872DA42B90920F00138637 /* BookmarkFolderInfo.swift in Sources */, + 7B60AFFE2C514269008E32A3 /* VPNURLEventHandler.swift in Sources */, B677FC502B06376B0099EB04 /* ReportFeedbackView.swift in Sources */, 3706FC68293F65D500E42796 /* ToggleableScrollView.swift in Sources */, 3706FC69293F65D500E42796 /* UserScripts.swift in Sources */, @@ -10574,6 +10630,7 @@ 4BCBE4552BA7E16600FC75A1 /* NetworkProtectionSubscriptionEventHandler.swift in Sources */, 371209312C233D69003ADF3D /* RemoteMessagingStoreErrorHandling.swift in Sources */, 3706FC83293F65D500E42796 /* PopoverMessageViewController.swift in Sources */, + 7B5A23702C46A116007213AC /* ExcludedDomainsModel.swift in Sources */, 4BF97ADA2B43C5DC00EB4240 /* VPNFeedbackCategory.swift in Sources */, 9D9AE86E2AA76D1F0026E7DC /* LoginItem+NetworkProtection.swift in Sources */, 3707C721294B5D2900682A9F /* WKMenuItemIdentifier.swift in Sources */, @@ -10608,6 +10665,7 @@ 3706FC9C293F65D500E42796 /* BookmarkStore.swift in Sources */, 3706FC9D293F65D500E42796 /* PrivacyDashboardViewController.swift in Sources */, B6A22B632B1E29D000ECD2BA /* DataImportSummaryViewModel.swift in Sources */, + 7BB4BC6B2C5CD96200E06FC8 /* ActiveDomainPublisher.swift in Sources */, 3706FC9E293F65D500E42796 /* PreferencesAppearanceView.swift in Sources */, 3706FC9F293F65D500E42796 /* NSMenuItemExtension.swift in Sources */, 3706FCA0293F65D500E42796 /* ContiguousBytesExtension.swift in Sources */, @@ -11076,6 +11134,7 @@ 7BA7CC402AD11E3D0042E5CE /* AppLauncher+DefaultInitializer.swift in Sources */, 7B0694982B6E980F00FA4DBA /* VPNProxyLauncher.swift in Sources */, BDA764842BC49E3F00D0400C /* NetworkProtectionVPNCountryLabelsModel.swift in Sources */, + 7B60AFFA2C511B65008E32A3 /* VPNUIActionHandler.swift in Sources */, B65DA5EF2A77CC3A00CBEE8D /* Bundle+NetworkProtectionExtensions.swift in Sources */, BDA7647F2BC4998900D0400C /* DefaultVPNLocationFormatter.swift in Sources */, 4BF0E5072AD2551A00FFEC9E /* NetworkProtectionPixelEvent.swift in Sources */, @@ -11115,6 +11174,7 @@ B65DA5F02A77CC3C00CBEE8D /* Bundle+NetworkProtectionExtensions.swift in Sources */, BDA764852BC49E4000D0400C /* NetworkProtectionVPNCountryLabelsModel.swift in Sources */, 7BAF9E4D2A8A3CCB002D3B6E /* UserDefaults+NetworkProtectionShared.swift in Sources */, + 7B60AFFB2C511C68008E32A3 /* VPNUIActionHandler.swift in Sources */, 7BA7CC392AD11E2D0042E5CE /* DuckDuckGoVPNAppDelegate.swift in Sources */, BDA764802BC4998A00D0400C /* DefaultVPNLocationFormatter.swift in Sources */, 7BA7CC552AD11FFB0042E5CE /* NetworkProtectionOptionKeyExtension.swift in Sources */, @@ -11388,6 +11448,7 @@ F18826912BC0105800D9AC4F /* PixelDataStore.swift in Sources */, B69B503E2726A12500758A2B /* AtbParser.swift in Sources */, 37F19A6528E1B3FB00740DC6 /* PreferencesDuckPlayerView.swift in Sources */, + 7B7F5D212C526CE600826256 /* AddExcludedDomainView.swift in Sources */, 4B92929E26670D2A00AD2C21 /* BookmarkSidebarTreeController.swift in Sources */, EEC4A6712B2C90AB00F7C0AA /* VPNLocationPreferenceItem.swift in Sources */, 85589E8727BBB8F20038AD11 /* HomePageFavoritesModel.swift in Sources */, @@ -11434,6 +11495,7 @@ 85774AFF2A713D3B00DE0561 /* BookmarksBarMenuFactory.swift in Sources */, 4B9292A026670D2A00AD2C21 /* SpacerNode.swift in Sources */, 3775913629AB9A1C00E26367 /* SyncManagementDialogViewController.swift in Sources */, + 7B7F5D242C52725A00826256 /* AddExcludedDomainButtonsView.swift in Sources */, B6C0BB6729AEFF8100AE8E3C /* BookmarkExtension.swift in Sources */, 4BE6547F271FCD4D008D1D63 /* PasswordManagementCreditCardModel.swift in Sources */, 31B4AF532901A4F20013585E /* NSEventExtension.swift in Sources */, @@ -11455,12 +11517,14 @@ 1D0DE93E2C3BA9840037ABC2 /* AppRestarter.swift in Sources */, 7BCB90C22C18626E008E3543 /* VPNControllerXPCClient+ConvenienceInitializers.swift in Sources */, 4B9DB0202A983B24000927DB /* ProductWaitlistRequest.swift in Sources */, + 7B60B0022C5145EC008E32A3 /* VPNUIActionHandler.swift in Sources */, 98779A0029999B64005D8EB6 /* Bookmark.xcdatamodeld in Sources */, 85589E9E27BFE4500038AD11 /* DefaultBrowserPromptView.swift in Sources */, 4B4032842AAAC24400CCA602 /* WaitlistActivationDateStore.swift in Sources */, 1D220BFC2B87AACF00F8BBC6 /* PrivacyProtectionStatus.swift in Sources */, AA512D1424D99D9800230283 /* FaviconManager.swift in Sources */, 7BB108592A43375D000AB95F /* PFMoveApplication.m in Sources */, + 7BB4BC632C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift in Sources */, 4B0AACAC28BC63ED001038AC /* ChromiumFaviconsReader.swift in Sources */, AABEE6AB24ACA0F90043105B /* SuggestionTableRowView.swift in Sources */, 37CD54CB27F2FDD100F1F7B9 /* DownloadsPreferences.swift in Sources */, @@ -11826,6 +11890,7 @@ C168B9AC2B31DC7E001AFAD9 /* AutofillNeverPromptWebsitesManager.swift in Sources */, 9FA173E72B7B122E00EE4E6E /* BookmarkDialogStackedContentView.swift in Sources */, F1C70D7C2BFF510000599292 /* SubscriptionEnvironment+Default.swift in Sources */, + 7B60AFFF2C51426A008E32A3 /* VPNURLEventHandler.swift in Sources */, D64A5FF82AEA5C2B00B6D6E7 /* HomeButtonMenuFactory.swift in Sources */, 37A6A8F62AFCCA59008580A3 /* FaviconsFetcherOnboardingViewController.swift in Sources */, AA3F895324C18AD500628DDE /* SuggestionViewModel.swift in Sources */, @@ -11833,6 +11898,7 @@ 4B723E1326B0007A00E14D75 /* CSVLoginExporter.swift in Sources */, B6BCC51E2AFCD9ED002C5499 /* DataImportSourcePicker.swift in Sources */, 85C48CCC278D808F00D3263E /* NSAttributedStringExtension.swift in Sources */, + 7B5A236F2C46A116007213AC /* ExcludedDomainsModel.swift in Sources */, 1D710F4B2C48F1F200C3975F /* UpdateDialogHelper.swift in Sources */, 4B41EDB42B168C55001EEDF4 /* VPNFeedbackFormViewModel.swift in Sources */, AA7EB6E527E7D6DC00036718 /* AnimationView.swift in Sources */, @@ -11955,6 +12021,7 @@ 1456D6E124EFCBC300775049 /* TabBarCollectionView.swift in Sources */, 4B4D60BF2A0C848A00BCD287 /* NetworkProtection+ConvenienceInitializers.swift in Sources */, 4B6B64842BA930420009FF9F /* WaitlistThankYouPromptPresenter.swift in Sources */, + 7B5A23682C468233007213AC /* ExcludedDomainsViewController.swift in Sources */, BDA7647C2BC497BE00D0400C /* DefaultVPNLocationFormatter.swift in Sources */, 3158B1592B0BF76400AF130C /* DataBrokerProtectionFeatureDisabler.swift in Sources */, B655124829A79465009BFE1C /* NavigationActionExtension.swift in Sources */, @@ -12058,6 +12125,7 @@ 37534CA8281198CD002621E7 /* AdjacentItemEnumerator.swift in Sources */, 7B7FCD0F2BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift in Sources */, 987799F62999996B005D8EB6 /* BookmarkDatabase.swift in Sources */, + 7BB4BC6A2C5CD96200E06FC8 /* ActiveDomainPublisher.swift in Sources */, 4BE53374286E39F10019DBFD /* ChromiumKeychainPrompt.swift in Sources */, B6553692268440D700085A79 /* WKProcessPool+GeolocationProvider.swift in Sources */, B68D21C32ACBC916002DA3C2 /* ContentBlockingMock.swift in Sources */, @@ -13364,7 +13432,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 180.0.0; + version = 180.0.1; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d08cec1c367..50bef80e9be 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "92ecebfb4172ab9561959a07d7ef7037aea8c6e1", - "version" : "180.0.0" + "revision" : "a3b3df069bbaa06149e43ca26e5df219ee61aa15", + "version" : "180.0.1" } }, { diff --git a/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser App Store.xcscheme b/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser App Store.xcscheme index e343e06df9f..7e937b1eb2f 100644 --- a/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser App Store.xcscheme +++ b/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser App Store.xcscheme @@ -145,6 +145,12 @@ + + + + + + + + Void private var didFinishLaunching = false @@ -109,7 +112,9 @@ final class URLEventHandler { private static func openURL(_ url: URL) { if url.scheme?.isNetworkProtectionScheme == true { - handleNetworkProtectionURL(url) + Task { @MainActor in + await vpnURLEventHandler.handle(url) + } } #if DBP @@ -141,38 +146,6 @@ final class URLEventHandler { } } - /// Handles NetP URLs - private static func handleNetworkProtectionURL(_ url: URL) { - DispatchQueue.main.async { - switch url { - case VPNAppLaunchCommand.showStatus.launchURL: - Task { - await WindowControllersManager.shared.showNetworkProtectionStatus() - } - case VPNAppLaunchCommand.showSettings.launchURL: - WindowControllersManager.shared.showPreferencesTab(withSelectedPane: .vpn) - case VPNAppLaunchCommand.shareFeedback.launchURL: - WindowControllersManager.shared.showShareFeedbackModal() - case VPNAppLaunchCommand.justOpen.launchURL: - WindowControllersManager.shared.showMainWindow() - case VPNAppLaunchCommand.showVPNLocations.launchURL: - WindowControllersManager.shared.showPreferencesTab(withSelectedPane: .vpn) - WindowControllersManager.shared.showLocationPickerSheet() - case VPNAppLaunchCommand.showPrivacyPro.launchURL: - let url = Application.appDelegate.subscriptionManager.url(for: .purchase) - WindowControllersManager.shared.showTab(with: .subscription(url)) - PixelKit.fire(PrivacyProPixel.privacyProOfferScreenImpression) -#if !APPSTORE && !DEBUG - case VPNAppLaunchCommand.moveAppToApplications.launchURL: - // this should be run after NSApplication.shared is set - PFMoveToApplicationsFolderIfNecessary(false) -#endif - default: - return - } - } - } - #if DBP /// Handles DBP URLs /// diff --git a/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift b/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift index 99d6f49afa7..4d8c4d348b0 100644 --- a/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift +++ b/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift @@ -124,6 +124,8 @@ extension UserText { // MARK: - Setting Titles // "vpn.location.title" - Location section title in VPN settings static let vpnLocationTitle = "Location" + // "vpn.excluded.sites.title" - Excluded Sites title in VPN settings + static let vpnExcludedSitesTitle = "Excluded Sites" // "vpn.general.title" - General section title in VPN settings static let vpnGeneralTitle = "General" // "vpn.shortcuts.settings.title" - Shortcuts section title in VPN settings @@ -161,6 +163,16 @@ extension UserText { return String(format: message, count) } + // MARK: - Excluded Domains + // "vpn.setting.excluded.domains.description" - Excluded Sites description + static let vpnExcludedDomainsDescription = "Websites you selected to be excluded even when the VPN is connected." + // "vpn.setting.excluded.domains.manage.button.title" - Excluded Sites management button title + static let vpnExcludedDomainsManageButtonTitle = "Manage Excluded Sites…" + // "vpn.excluded.domains.add.domain" - Add Domain button for the excluded sites view + static let vpnExcludedDomainsAddDomain = "Add Website" + // "vpn.excluded.domains.title" - Title for the excluded sites view + static let vpnExcludedDomainsTitle = "Excluded Websites" + // MARK: - DNS // "vpn.dns.server.title" - Title of the DNS Server section static let vpnDnsServerTitle = "DNS Server" diff --git a/DuckDuckGo/Localizable.xcstrings b/DuckDuckGo/Localizable.xcstrings index b21ce803f6d..cfe2bc8a52c 100644 --- a/DuckDuckGo/Localizable.xcstrings +++ b/DuckDuckGo/Localizable.xcstrings @@ -57121,6 +57121,9 @@ } } } + }, + "URL" : { + }, "version" : { "comment" : "Displays the version and build numbers", diff --git a/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift b/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift index 10e3549432c..b92afe8eac1 100644 --- a/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift +++ b/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift @@ -29,6 +29,7 @@ protocol PopoverPresenter { func show(_ popover: NSPopover, positionedBelow view: NSView) } +@MainActor protocol NetPPopoverManager: AnyObject { var isShown: Bool { get } @@ -133,8 +134,10 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter { } func toggleNetworkProtectionPopover(from button: MouseOverButton, withDelegate delegate: NSPopoverDelegate) { - if let popover = networkProtectionPopoverManager.toggle(positionedBelow: button, withDelegate: delegate) { - bindIsMouseDownState(of: button, to: popover) + Task { @MainActor in + if let popover = networkProtectionPopoverManager.toggle(positionedBelow: button, withDelegate: delegate) { + bindIsMouseDownState(of: button, to: popover) + } } } @@ -199,8 +202,10 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter { downloadsPopover?.close() } - if networkProtectionPopoverManager.isShown { - networkProtectionPopoverManager.close() + Task { @MainActor in + if networkProtectionPopoverManager.isShown { + networkProtectionPopoverManager.close() + } } if bookmarkPopover?.isShown ?? false { @@ -432,8 +437,11 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter { // MARK: - VPN func showNetworkProtectionPopover(positionedBelow button: MouseOverButton, withDelegate delegate: NSPopoverDelegate) { - let popover = networkProtectionPopoverManager.show(positionedBelow: button, withDelegate: delegate) - bindIsMouseDownState(of: button, to: popover) + + Task { @MainActor in + let popover = networkProtectionPopoverManager.show(positionedBelow: button, withDelegate: delegate) + bindIsMouseDownState(of: button, to: popover) + } } } diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/ActiveDomainPublisher.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/ActiveDomainPublisher.swift new file mode 100644 index 00000000000..9caf65a9ec2 --- /dev/null +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/ActiveDomainPublisher.swift @@ -0,0 +1,100 @@ +// +// ActiveDomainPublisher.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine +import Foundation + +/// A convenience class for publishing the active domain +/// +/// The active domain is the domain loaded in the last active tab within the last active window. +/// +final class ActiveDomainPublisher { + + private let windowControllersManager: WindowControllersManager + private var activeWindowControllerCancellable: AnyCancellable? + private var activeTabViewModelCancellable: AnyCancellable? + private var activeTabContentCancellable: AnyCancellable? + + @MainActor + @Published + private var activeWindowController: MainWindowController? { + didSet { + subscribeToActiveTabViewModel() + } + } + + @MainActor + @Published + private var activeTab: Tab? { + didSet { + subscribeToActiveTabContentChanges() + } + } + + init(windowControllersManager: WindowControllersManager) { + self.windowControllersManager = windowControllersManager + + Task { @MainActor in + subscribeToKeyWindowControllerChanges() + } + } + + @Published + private(set) var activeDomain: String? + + @MainActor + private func subscribeToKeyWindowControllerChanges() { + activeWindowControllerCancellable = windowControllersManager + .didChangeKeyWindowController + .prepend(windowControllersManager.lastKeyMainWindowController) + .assign(to: \.activeWindowController, onWeaklyHeld: self) + } + + @MainActor + private func subscribeToActiveTabViewModel() { + activeTabViewModelCancellable = activeWindowController?.mainViewController.tabCollectionViewModel.$selectedTabViewModel + .map(\.?.tab) + .assign(to: \.activeTab, onWeaklyHeld: self) + } + + @MainActor + private func subscribeToActiveTabContentChanges() { + activeTabContentCancellable = activeTab?.$content + .map(domain(from:)) + .removeDuplicates() + .assign(to: \.activeDomain, onWeaklyHeld: self) + } + + private func domain(from tabContent: Tab.TabContent) -> String? { + if case .url(let url, _, _) = tabContent { + + return url.host + } else { + return nil + } + } +} + +extension ActiveDomainPublisher: Publisher { + typealias Output = String? + typealias Failure = Never + + func receive(subscriber: S) where S: Subscriber, Never == S.Failure, String? == S.Input { + $activeDomain.subscribe(subscriber) + } +} diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift index 3bc4345a919..9afbacf5195 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift @@ -82,6 +82,14 @@ final class NetworkProtectionDebugMenu: NSMenu { NSMenuItem.separator() + NSMenuItem(title: "Adapter") { + NSMenuItem(title: "Restart Adapter", action: #selector(NetworkProtectionDebugMenu.restartAdapter(_:))) + .targetting(self) + + NSMenuItem(title: "Re-create Adapter", action: #selector(NetworkProtectionDebugMenu.restartAdapter(_:))) + .targetting(self) + } + NSMenuItem(title: "Tunnel Settings") { shouldIncludeAllNetworksMenuItem .targetting(self) @@ -218,6 +226,18 @@ final class NetworkProtectionDebugMenu: NSMenu { } } + /// Removes the system extension and agents for DuckDuckGo VPN. + /// + @objc func restartAdapter(_ sender: Any?) { + Task { @MainActor in + do { + try await debugUtilities.restartAdapter() + } catch { + await NSAlert(error: error).runModal() + } + } + } + /// Sends a test user notification. /// @objc func sendTestNotification(_ sender: Any?) { @@ -449,8 +469,8 @@ final class NetworkProtectionDebugMenu: NSMenu { private let ddgBrowserAppIdentifier = Bundle.main.bundleIdentifier! private func updateExclusionsMenu() { - excludeDBPTrafficFromVPN.state = transparentProxySettings.isExcluding(dbpBackgroundAppIdentifier) ? .on : .off - excludeDDGBrowserTrafficFromVPN.state = transparentProxySettings.isExcluding(ddgBrowserAppIdentifier) ? .on : .off + excludeDBPTrafficFromVPN.state = transparentProxySettings.isExcluding(appIdentifier: dbpBackgroundAppIdentifier) ? .on : .off + excludeDDGBrowserTrafficFromVPN.state = transparentProxySettings.isExcluding(appIdentifier: ddgBrowserAppIdentifier) ? .on : .off } @objc private func toggleExcludeDBPBackgroundAgent() { diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift index 8f3a0857346..d8d744f6849 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift @@ -54,6 +54,10 @@ final class NetworkProtectionDebugUtilities { // MARK: - Debug commands for the extension + func restartAdapter() async throws { + try await ipcClient.command(.restartAdapter) + } + func resetAllState(keepAuthToken: Bool) async throws { try await vpnUninstaller.uninstall(removeSystemExtension: true) diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift index 6b553616113..6573e3a550c 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift @@ -19,6 +19,7 @@ import AppLauncher import AppKit import Combine +import Common import Foundation import LoginItems import NetworkProtection @@ -26,6 +27,8 @@ import NetworkProtectionIPC import NetworkProtectionUI import Subscription import VPNAppLauncher +import SwiftUI +import NetworkProtectionProxy protocol NetworkProtectionIPCClient { var ipcStatusObserver: ConnectionStatusObserver { get } @@ -44,15 +47,36 @@ extension VPNControllerXPCClient: NetworkProtectionIPCClient { public var ipcDataVolumeObserver: any NetworkProtection.DataVolumeObserver { dataVolumeObserver } } +@MainActor final class NetworkProtectionNavBarPopoverManager: NetPPopoverManager { private var networkProtectionPopover: NetworkProtectionPopover? let ipcClient: NetworkProtectionIPCClient let vpnUninstaller: VPNUninstalling + @Published + private var siteInfo: SiteTroubleshootingInfo? + private let siteTroubleshootingInfoPublisher: SiteTroubleshootingInfoPublisher + private var cancellables = Set() + init(ipcClient: VPNControllerXPCClient, vpnUninstaller: VPNUninstalling) { + self.ipcClient = ipcClient self.vpnUninstaller = vpnUninstaller + + let activeDomainPublisher = ActiveDomainPublisher(windowControllersManager: .shared) + + siteTroubleshootingInfoPublisher = SiteTroubleshootingInfoPublisher( + activeDomainPublisher: activeDomainPublisher.eraseToAnyPublisher(), + proxySettings: TransparentProxySettings(defaults: .netP)) + + subscribeToCurrentSitePublisher() + } + + private func subscribeToCurrentSitePublisher() { + siteTroubleshootingInfoPublisher + .assign(to: \.siteInfo, onWeaklyHeld: self) + .store(in: &cancellables) } var isShown: Bool { @@ -60,8 +84,7 @@ final class NetworkProtectionNavBarPopoverManager: NetPPopoverManager { } func show(positionedBelow view: NSView, withDelegate delegate: NSPopoverDelegate) -> NSPopover { - let popover = { - + let popover: NSPopover = { let controller = NetworkProtectionIPCTunnelController(ipcClient: ipcClient) let statusReporter = DefaultNetworkProtectionStatusReporter( @@ -77,12 +100,23 @@ final class NetworkProtectionNavBarPopoverManager: NetPPopoverManager { let onboardingStatusPublisher = UserDefaults.netP.networkProtectionOnboardingStatusPublisher _ = VPNSettings(defaults: .netP) let appLauncher = AppLauncher(appBundleURL: Bundle.main.bundleURL) - - let popover = NetworkProtectionPopover(controller: controller, - onboardingStatusPublisher: onboardingStatusPublisher, - statusReporter: statusReporter, - uiActionHandler: appLauncher, - menuItems: { + let vpnURLEventHandler = VPNURLEventHandler() + let proxySettings = TransparentProxySettings(defaults: .netP) + let uiActionHandler = VPNUIActionHandler(vpnURLEventHandler: vpnURLEventHandler, proxySettings: proxySettings) + + let siteTroubleshootingFeatureFlagPublisher = NSApp.delegateTyped.internalUserDecider.isInternalUserPublisher.eraseToAnyPublisher() + + let siteTroubleshootingViewModel = SiteTroubleshootingView.Model( + featureFlagPublisher: siteTroubleshootingFeatureFlagPublisher, + connectionStatusPublisher: statusReporter.statusObserver.publisher, + siteTroubleshootingInfoPublisher: $siteInfo.eraseToAnyPublisher(), + uiActionHandler: uiActionHandler) + + let statusViewModel = NetworkProtectionStatusView.Model(controller: controller, + onboardingStatusPublisher: onboardingStatusPublisher, + statusReporter: statusReporter, + uiActionHandler: uiActionHandler, + menuItems: { if UserDefaults.netP.networkProtectionOnboardingStatus == .completed { return [ NetworkProtectionStatusView.Model.MenuItem( @@ -113,13 +147,19 @@ final class NetworkProtectionNavBarPopoverManager: NetPPopoverManager { ] } }, - agentLoginItem: LoginItem.vpnMenu, - isMenuBarStatusView: false, - userDefaults: .netP, - locationFormatter: DefaultVPNLocationFormatter(), - uninstallHandler: { [weak self] in + agentLoginItem: LoginItem.vpnMenu, + isMenuBarStatusView: false, + userDefaults: .netP, + locationFormatter: DefaultVPNLocationFormatter(), + uninstallHandler: { [weak self] in _ = try? await self?.vpnUninstaller.uninstall(removeSystemExtension: true) }) + + let popover = NetworkProtectionPopover( + statusViewModel: statusViewModel, + statusReporter: statusReporter, + siteTroubleshootingViewModel: siteTroubleshootingViewModel, + debugInformationViewModel: DebugInformationViewModel(showDebugInformation: false)) popover.delegate = delegate networkProtectionPopover = popover diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift index 899897dfcea..78d6cda52f7 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift @@ -111,13 +111,6 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr // MARK: - User Defaults - /* Temporarily disabled - https://app.asana.com/0/0/1205766100762904/f - /// Test setting to exclude duckduckgo route from VPN - @MainActor - @UserDefaultsWrapper(key: .networkProtectionExcludedRoutes, defaultValue: [:]) - private(set) var excludedRoutesPreferences: [String: Bool] - */ - @UserDefaultsWrapper(key: .networkProtectionOnboardingStatusRawValue, defaultValue: OnboardingStatus.default.rawValue, defaults: .netP) private(set) var onboardingStatusRawValue: OnboardingStatus.RawValue diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/SiteTroubleshootingInfoPublisher.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/SiteTroubleshootingInfoPublisher.swift new file mode 100644 index 00000000000..5a3d5684148 --- /dev/null +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/SiteTroubleshootingInfoPublisher.swift @@ -0,0 +1,111 @@ +// +// SiteTroubleshootingInfoPublisher.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine +import Foundation +import NetworkProtectionProxy +import NetworkProtectionUI + +@MainActor +final class SiteTroubleshootingInfoPublisher { + + private var activeDomain: String? { + didSet { + refreshSiteTroubleshootingInfo() + } + } + + private let subject: CurrentValueSubject + + private let activeDomainPublisher: AnyPublisher + private let proxySettings: TransparentProxySettings + private var cancellables = Set() + + init(activeDomainPublisher: AnyPublisher, + proxySettings: TransparentProxySettings) { + + subject = CurrentValueSubject(nil) + self.activeDomainPublisher = activeDomainPublisher + self.proxySettings = proxySettings + + subscribeToActiveDomainChanges() + subscribeToExclusionChanges() + } + + private func subscribeToActiveDomainChanges() { + activeDomainPublisher + .assign(to: \.activeDomain, onWeaklyHeld: self) + .store(in: &cancellables) + } + + private func subscribeToExclusionChanges() { + proxySettings.changePublisher.sink { [weak self] change in + guard let self else { return } + + switch change { + case .excludedDomains: + refreshSiteTroubleshootingInfo() + default: + break + } + }.store(in: &cancellables) + } + + // MARK: - Refreshing + + func refreshSiteTroubleshootingInfo() { + if activeSiteTroubleshootingInfo != subject.value { + subject.send(activeSiteTroubleshootingInfo) + } + } + + // MARK: - Active Site Troubleshooting Info + + var activeSiteTroubleshootingInfo: SiteTroubleshootingInfo? { + guard let activeDomain else { + return nil + } + + return site(forDomain: activeDomain.droppingWwwPrefix()) + } + + private func site(forDomain domain: String) -> SiteTroubleshootingInfo? { + let icon: NSImage? + let currentSite: NetworkProtectionUI.SiteTroubleshootingInfo? + + icon = FaviconManager.shared.getCachedFavicon(for: domain, sizeCategory: .small)?.image + let proxySettings = TransparentProxySettings(defaults: .netP) + currentSite = NetworkProtectionUI.SiteTroubleshootingInfo( + icon: icon, + domain: domain, + excluded: proxySettings.isExcluding(domain: domain)) + + return currentSite + } +} + +extension SiteTroubleshootingInfoPublisher: Publisher { + typealias Output = SiteTroubleshootingInfo? + typealias Failure = Never + + nonisolated + func receive(subscriber: S) where S: Subscriber, Never == S.Failure, NetworkProtectionUI.SiteTroubleshootingInfo? == S.Input { + + subject.receive(subscriber: subscriber) + } +} diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNUIActionHandler.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNUIActionHandler.swift new file mode 100644 index 00000000000..53db14808bd --- /dev/null +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNUIActionHandler.swift @@ -0,0 +1,65 @@ +// +// VPNUIActionHandler.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import AppLauncher +import Foundation +import NetworkProtectionIPC +import NetworkProtectionProxy +import NetworkProtectionUI +import VPNAppLauncher + +/// Main App's VPN UI action handler +/// +final class VPNUIActionHandler: VPNUIActionHandling { + + private let vpnIPCClient: VPNControllerXPCClient + private let proxySettings: TransparentProxySettings + private let vpnURLEventHandler: VPNURLEventHandler + + init(vpnIPCClient: VPNControllerXPCClient = .shared, + vpnURLEventHandler: VPNURLEventHandler, + proxySettings: TransparentProxySettings) { + + self.vpnIPCClient = vpnIPCClient + self.vpnURLEventHandler = vpnURLEventHandler + self.proxySettings = proxySettings + } + + public func moveAppToApplications() async { +#if !APPSTORE && !DEBUG + await vpnURLEventHandler.moveAppToApplicationsFolder() +#endif + } + + func setExclusion(_ exclude: Bool, forDomain domain: String) async { + proxySettings.setExclusion(exclude, forDomain: domain) + try? await vpnIPCClient.command(.restartAdapter) + } + + public func shareFeedback() async { + await vpnURLEventHandler.showShareFeedback() + } + + public func showVPNLocations() async { + await vpnURLEventHandler.showLocations() + } + + public func showPrivacyPro() async { + await vpnURLEventHandler.showPrivacyPro() + } +} diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNURLEventHandler.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNURLEventHandler.swift new file mode 100644 index 00000000000..54368bc09e1 --- /dev/null +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNURLEventHandler.swift @@ -0,0 +1,91 @@ +// +// VPNURLEventHandler.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import PixelKit +import VPNAppLauncher + +@MainActor +final class VPNURLEventHandler { + + private let windowControllerManager: WindowControllersManager + + init(windowControllerManager: WindowControllersManager? = nil) { + self.windowControllerManager = windowControllerManager ?? .shared + } + + /// Handles VPN event URLs + /// + func handle(_ url: URL) async { + switch url { + case VPNAppLaunchCommand.showStatus.launchURL: + await showStatus() + case VPNAppLaunchCommand.showSettings.launchURL: + showPreferences() + case VPNAppLaunchCommand.shareFeedback.launchURL: + showShareFeedback() + case VPNAppLaunchCommand.justOpen.launchURL: + showMainWindow() + case VPNAppLaunchCommand.showVPNLocations.launchURL: + showLocations() + case VPNAppLaunchCommand.showPrivacyPro.launchURL: + showPrivacyPro() +#if !APPSTORE && !DEBUG + case VPNAppLaunchCommand.moveAppToApplications.launchURL: + moveAppToApplicationsFolder() +#endif + default: + return + } + } + + func showStatus() async { + await windowControllerManager.showNetworkProtectionStatus() + } + + func showPreferences() { + windowControllerManager.showPreferencesTab(withSelectedPane: .vpn) + } + + func showShareFeedback() { + windowControllerManager.showShareFeedbackModal() + } + + func showMainWindow() { + windowControllerManager.showMainWindow() + } + + func showLocations() { + windowControllerManager.showPreferencesTab(withSelectedPane: .vpn) + windowControllerManager.showLocationPickerSheet() + } + + func showPrivacyPro() { + let url = Application.appDelegate.subscriptionManager.url(for: .purchase) + windowControllerManager.showTab(with: .subscription(url)) + + PixelKit.fire(PrivacyProPixel.privacyProOfferScreenImpression) + } + +#if !APPSTORE && !DEBUG + func moveAppToApplicationsFolder() { + // this should be run after NSApplication.shared is set + PFMoveToApplicationsFolderIfNecessary(false) + } +#endif +} diff --git a/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainButtonsView.swift b/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainButtonsView.swift new file mode 100644 index 00000000000..c4db9dafc0f --- /dev/null +++ b/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainButtonsView.swift @@ -0,0 +1,187 @@ +// +// AddExcludedDomainButtonsView.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import SwiftUI + +struct AddExcludedDomainButtonsView: View { + private let viewState: ViewState + private let otherButtonAction: Action + private let defaultButtonAction: Action + @Environment(\.dismiss) private var dismiss + + init( + viewState: ViewState, + otherButtonAction: Action, + defaultButtonAction: Action + ) { + self.viewState = viewState + self.otherButtonAction = otherButtonAction + self.defaultButtonAction = defaultButtonAction + } + + var body: some View { + HStack { + if viewState == .compressed { + Spacer() + } + + actionButton(action: otherButtonAction, viewState: viewState).accessibilityIdentifier("AddExcludedDomainButtonsView.otherButton") + + actionButton(action: defaultButtonAction, viewState: viewState).accessibilityIdentifier("AddExcludedDomainButtonsView.defaultButton") + } + } + + @MainActor + private func actionButton(action: Action, viewState: ViewState) -> some View { + Button { + action.action(dismiss.callAsFunction) + } label: { + Text(action.title) + .frame(height: viewState.height) + .frame(maxWidth: viewState.maxWidth) + } + .keyboardShortcut(action.keyboardShortCut) + .disabled(action.isDisabled) + .ifLet(action.accessibilityIdentifier) { view, value in + view.accessibilityIdentifier(value) + } + } +} + +// MARK: - BookmarkDialogButtonsView + Types + +extension AddExcludedDomainButtonsView { + + enum ViewState: Equatable { + case compressed + case expanded + } + + struct Action { + let title: String + let keyboardShortCut: KeyboardShortcut? + let accessibilityIdentifier: String? + let isDisabled: Bool + let action: @MainActor (_ dismiss: () -> Void) -> Void + + init( + title: String, + accessibilityIdentifier: String? = nil, + keyboardShortCut: KeyboardShortcut? = nil, + isDisabled: Bool = false, + action: @MainActor @escaping (_ dismiss: () -> Void) -> Void + ) { + self.title = title + self.keyboardShortCut = keyboardShortCut + self.accessibilityIdentifier = accessibilityIdentifier + self.isDisabled = isDisabled + self.action = action + } + } +} + +// MARK: - BookmarkDialogButtonsView.ViewState + +private extension AddExcludedDomainButtonsView.ViewState { + + var maxWidth: CGFloat? { + switch self { + case .compressed: + return nil + case .expanded: + return .infinity + } + } + + var height: CGFloat? { + switch self { + case .compressed: + return nil + case .expanded: + return 28.0 + } + } + +} + +// MARK: - Preview + +#Preview("Compressed - Disable Default Button") { + AddExcludedDomainButtonsView( + viewState: .compressed, + otherButtonAction: .init( + title: "Left", + action: { _ in } + ), + defaultButtonAction: .init( + title: "Right", + isDisabled: true, + action: {_ in } + ) + ) + .frame(width: 320, height: 50) +} + +#Preview("Compressed - Enabled Default Button") { + AddExcludedDomainButtonsView( + viewState: .compressed, + otherButtonAction: .init( + title: "Left", + action: { _ in } + ), + defaultButtonAction: .init( + title: "Right", + isDisabled: false, + action: {_ in } + ) + ) + .frame(width: 320, height: 50) +} + +#Preview("Expanded - Disable Default Button") { + AddExcludedDomainButtonsView( + viewState: .expanded, + otherButtonAction: .init( + title: "Left", + action: { _ in } + ), + defaultButtonAction: .init( + title: "Right", + isDisabled: true, + action: {_ in } + ) + ) + .frame(width: 320, height: 50) +} + +#Preview("Expanded - Enable Default Button") { + AddExcludedDomainButtonsView( + viewState: .expanded, + otherButtonAction: .init( + title: "Left", + action: { _ in } + ), + defaultButtonAction: .init( + title: "Right", + isDisabled: false, + action: {_ in } + ) + ) + .frame(width: 320, height: 50) +} diff --git a/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainView.swift b/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainView.swift new file mode 100644 index 00000000000..d79d26d0d1f --- /dev/null +++ b/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainView.swift @@ -0,0 +1,112 @@ +// +// AddExcludedDomainView.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import SwiftUI +import SwiftUIExtensions + +struct AddExcludedDomainView: ModalView { + enum ButtonsState { + case compressed + case expanded + } + + let title: String + let buttonsState: ButtonsState + + @State + private var domain = "" + + let cancelActionTitle: String + let cancelAction: @MainActor (_ dismiss: () -> Void) -> Void + + let defaultActionTitle: String + @State + private var isDefaultActionDisabled = true + let defaultAction: @MainActor (_ domain: String, _ dismiss: () -> Void) -> Void + + var body: some View { + TieredDialogView( + verticalSpacing: 16.0, + horizontalPadding: 20.0, + top: { + Text(title) + .foregroundColor(.primary) + .fontWeight(.semibold) + .padding(.top, 20) + }, + center: { + form + }, + bottom: { + AddExcludedDomainButtonsView( + viewState: .init(buttonsState), + otherButtonAction: .init( + title: cancelActionTitle, + keyboardShortCut: .cancelAction, + isDisabled: false, + action: cancelAction + ), defaultButtonAction: .init( + title: defaultActionTitle, + keyboardShortCut: .defaultAction, + isDisabled: isDefaultActionDisabled, + action: { dismiss in + defaultAction(domain, dismiss) + } + ) + ).padding(.bottom, 16.0) + } + ).font(.system(size: 13)) + .frame(width: 420) + } + + var form: some View { + TwoColumnsListView( + horizontalSpacing: 16.0, + verticalSpacing: 20.0, + rowHeight: 22.0, + leftColumn: { + Text("URL") + .foregroundColor(.primary) + .fontWeight(.medium) + }, + rightColumn: { + TextField("", text: $domain) + .focusedOnAppear() + .onChange(of: domain) { _ in + isDefaultActionDisabled = !domain.isValidHostname + } + .accessibilityIdentifier("bookmark.add.name.textfield") + .textFieldStyle(RoundedBorderTextFieldStyle()) + .font(.system(size: 14)) + } + ) + } +} + +private extension AddExcludedDomainButtonsView.ViewState { + + init(_ state: AddExcludedDomainView.ButtonsState) { + switch state { + case .compressed: + self = .compressed + case .expanded: + self = .expanded + } + } +} diff --git a/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomains.storyboard b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomains.storyboard new file mode 100644 index 00000000000..30ffd0b64fb --- /dev/null +++ b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomains.storyboard @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsModel.swift b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsModel.swift new file mode 100644 index 00000000000..b3cbdbd75ea --- /dev/null +++ b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsModel.swift @@ -0,0 +1,54 @@ +// +// ExcludedDomainsModel.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import NetworkProtectionProxy + +protocol ExcludedDomainsViewModel { + var domains: [String] { get } + + func add(domain: String) + func remove(domain: String) +} + +final class DefaultExcludedDomainsViewModel { + let proxySettings = TransparentProxySettings(defaults: .netP) + + init() { + } +} + +extension DefaultExcludedDomainsViewModel: ExcludedDomainsViewModel { + var domains: [String] { + proxySettings.excludedDomains + } + + func add(domain: String) { + guard !proxySettings.excludedDomains.contains(domain) else { + return + } + + proxySettings.excludedDomains.append(domain) + } + + func remove(domain: String) { + proxySettings.excludedDomains.removeAll { cursor in + domain == cursor + } + } +} diff --git a/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsViewController.swift b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsViewController.swift new file mode 100644 index 00000000000..6192405f211 --- /dev/null +++ b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsViewController.swift @@ -0,0 +1,178 @@ +// +// ExcludedDomainsViewController.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import AppKit + +final class ExcludedDomainsViewController: NSViewController { + typealias Model = ExcludedDomainsViewModel + + enum Constants { + static let storyboardName = "ExcludedDomains" + static let identifier = "ExcludedDomainsViewController" + static let cellIdentifier = NSUserInterfaceItemIdentifier(rawValue: "ExcludedDomainCell") + } + + static func create(model: Model = DefaultExcludedDomainsViewModel()) -> ExcludedDomainsViewController { + let storyboard = loadStoryboard() + + return storyboard.instantiateController(identifier: Constants.identifier) { coder in + ExcludedDomainsViewController(model: model, coder: coder) + } + } + + static func loadStoryboard() -> NSStoryboard { + NSStoryboard(name: Constants.storyboardName, bundle: nil) + } + + @IBOutlet var tableView: NSTableView! + @IBOutlet var addDomainButton: NSButton! + @IBOutlet var removeDomainButton: NSButton! + @IBOutlet var doneButton: NSButton! + @IBOutlet var excludedDomainsLabel: NSTextField! + + private let faviconManagement: FaviconManagement = FaviconManager.shared + + private var allDomains = [String]() + private var filteredDomains: [String]? + + private var visibleDomains: [String] { + return filteredDomains ?? allDomains + } + + private let model: Model + + init?(model: Model, coder: NSCoder) { + self.model = model + + super.init(coder: coder) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + applyModalWindowStyleIfNeeded() + reloadData() + setUpStrings() + } + + private func setUpStrings() { + addDomainButton.title = UserText.vpnExcludedDomainsAddDomain + removeDomainButton.title = UserText.remove + doneButton.title = UserText.done + excludedDomainsLabel.stringValue = UserText.vpnExcludedDomainsTitle + } + + private func updateRemoveButtonState() { + removeDomainButton.isEnabled = tableView.selectedRow > -1 + } + + fileprivate func reloadData() { + allDomains = model.domains.sorted { (lhs, rhs) -> Bool in + return lhs < rhs + } + + tableView.reloadData() + updateRemoveButtonState() + } + + @IBAction func doneButtonClicked(_ sender: NSButton) { + dismiss() + } + + @IBAction func addDomain(_ sender: NSButton) { + AddExcludedDomainView(title: "Add Website Exclusion", buttonsState: .compressed, cancelActionTitle: "Cancel", cancelAction: { dismiss in + + dismiss() + }, defaultActionTitle: "Add Website") { [weak self] domain, dismiss in + guard let self else { return } + + addDomain(domain) + dismiss() + }.show(in: view.window) + } + + private func addDomain(_ domain: String) { + model.add(domain: domain) + reloadData() + + if let newRowIndex = allDomains.firstIndex(of: domain) { + tableView.scrollRowToVisible(newRowIndex) + } + } + + @IBAction func removeSelectedDomain(_ sender: NSButton) { + guard tableView.selectedRow > -1 else { + updateRemoveButtonState() + return + } + + let selectedDomain = visibleDomains[tableView.selectedRow] + model.remove(domain: selectedDomain) + reloadData() + } +} + +extension ExcludedDomainsViewController: NSTableViewDataSource, NSTableViewDelegate { + + func numberOfRows(in tableView: NSTableView) -> Int { + return visibleDomains.count + } + + func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { + return visibleDomains[row] + } + + func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { + guard let cell = tableView.makeView(withIdentifier: Constants.cellIdentifier, owner: nil) as? NSTableCellView else { + + return nil + } + + let domain = visibleDomains[row] + + cell.textField?.stringValue = domain + cell.imageView?.image = faviconManagement.getCachedFavicon(for: domain, sizeCategory: .small)?.image + cell.imageView?.applyFaviconStyle() + + return cell + } + + func tableViewSelectionDidChange(_ notification: Notification) { + updateRemoveButtonState() + } +} + +extension ExcludedDomainsViewController: NSTextFieldDelegate { + + func controlTextDidChange(_ notification: Notification) { + guard let field = notification.object as? NSSearchField else { return } + + if field.stringValue.isEmpty { + filteredDomains = nil + } else { + filteredDomains = allDomains.filter { $0.contains(field.stringValue) } + } + + reloadData() + } + +} diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift index 0e856edf95f..bf2e66e6642 100644 --- a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -20,6 +20,7 @@ import AppKit import Combine import Foundation import NetworkProtection +import NetworkProtectionIPC import NetworkProtectionUI import BrowserServicesKit @@ -38,6 +39,9 @@ final class VPNPreferencesModel: ObservableObject { @Published var excludeLocalNetworks: Bool { didSet { settings.excludeLocalNetworks = excludeLocalNetworks + Task { + try await vpnXPCClient.command(.restartAdapter) + } } } @@ -59,6 +63,13 @@ final class VPNPreferencesModel: ObservableObject { } } + /// Whether the excluded sites section in preferences is shown. + /// + /// Only necessary because this is feature flagged to internal users. + /// + @Published + var showExcludedSites: Bool + @Published var notifyStatusChanges: Bool { didSet { settings.notifyStatusChanges = notifyStatusChanges @@ -74,19 +85,25 @@ final class VPNPreferencesModel: ObservableObject { } @Published public var dnsSettings: NetworkProtectionDNSSettings = .default - @Published public var isCustomDNSSelected = false @Published public var customDNSServers: String? + private let vpnXPCClient: VPNControllerXPCClient private let settings: VPNSettings private let pinningManager: PinningManager + private let internalUserDecider: InternalUserDecider private var cancellables = Set() - init(settings: VPNSettings = .init(defaults: .netP), + init(vpnXPCClient: VPNControllerXPCClient = .shared, + settings: VPNSettings = .init(defaults: .netP), pinningManager: PinningManager = LocalPinningManager.shared, - defaults: UserDefaults = .netP) { + defaults: UserDefaults = .netP, + internalUserDecider: InternalUserDecider = NSApp.delegateTyped.internalUserDecider) { + + self.vpnXPCClient = vpnXPCClient self.settings = settings self.pinningManager = pinningManager + self.internalUserDecider = internalUserDecider connectOnLogin = settings.connectOnLogin excludeLocalNetworks = settings.excludeLocalNetworks @@ -94,6 +111,7 @@ final class VPNPreferencesModel: ObservableObject { showInMenuBar = settings.showInMenuBar showInBrowserToolbar = pinningManager.isPinned(.networkProtection) showUninstallVPN = defaults.networkProtectionOnboardingStatus != .default + showExcludedSites = internalUserDecider.isInternalUser onboardingStatus = defaults.networkProtectionOnboardingStatus locationItem = VPNLocationPreferenceItemModel(selectedLocation: settings.selectedLocation) @@ -102,6 +120,7 @@ final class VPNPreferencesModel: ObservableObject { subscribeToShowInBrowserToolbarSettingsChanges() subscribeToLocationSettingChanges() subscribeToDNSSettingsChanges() + subscribeToInternalUserChanges() } func subscribeToOnboardingStatusChanges(defaults: UserDefaults) { @@ -150,6 +169,12 @@ final class VPNPreferencesModel: ObservableObject { customDNSServers = settings.dnsSettings.dnsServersText } + private func subscribeToInternalUserChanges() { + internalUserDecider.isInternalUserPublisher + .assign(to: \.showExcludedSites, onWeaklyHeld: self) + .store(in: &cancellables) + } + func resetDNSSettings() { settings.dnsSettings = .default } @@ -182,6 +207,22 @@ final class VPNPreferencesModel: ObservableObject { return alert } + + // MARK: - Excluded Sites + + @MainActor + func manageExcludedSites() { + let windowController = ExcludedDomainsViewController.create().wrappedInWindowController() + + guard let window = windowController.window, + let parentWindowController = WindowControllersManager.shared.lastKeyMainWindowController + else { + assertionFailure("DataClearingPreferences: Failed to present ExcludedDomainsViewController") + return + } + + parentWindowController.window?.beginSheet(window) + } } extension NetworkProtectionDNSSettings { diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index 10ef5fd0901..7d0c793bc29 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -55,7 +55,24 @@ extension Preferences { } .padding(.bottom, 12) - // SECTION: Manage VPN + // SECTION: Excluded Sites + + if model.showExcludedSites { + PreferencePaneSection(UserText.vpnExcludedSitesTitle, spacing: 4) { + Text(UserText.vpnExcludedDomainsDescription) + .foregroundColor(.secondary) + .padding(.bottom, 18) + + PreferencePaneSubSection { + Button(UserText.vpnExcludedDomainsManageButtonTitle) { + model.manageExcludedSites() + } + } + } + .padding(.bottom, 12) + } + + // SECTION: General PreferencePaneSection(UserText.vpnGeneralTitle) { diff --git a/DuckDuckGo/Tab/View/BrowserTabViewController.swift b/DuckDuckGo/Tab/View/BrowserTabViewController.swift index d9c696c8200..779e35dc471 100644 --- a/DuckDuckGo/Tab/View/BrowserTabViewController.swift +++ b/DuckDuckGo/Tab/View/BrowserTabViewController.swift @@ -1193,7 +1193,7 @@ extension BrowserTabViewController { private func subscribeToTabSelectedInCurrentKeyWindow() { let lastKeyWindowOtherThanOurs = WindowControllersManager.shared.didChangeKeyWindowController - .map { WindowControllersManager.shared.lastKeyMainWindowController } + .map { $0 } .prepend(WindowControllersManager.shared.lastKeyMainWindowController) .compactMap { $0 } .filter { [weak self] in $0.window !== self?.view.window } diff --git a/DuckDuckGo/Windows/View/WindowControllersManager.swift b/DuckDuckGo/Windows/View/WindowControllersManager.swift index f597e7432eb..e21c96bc99e 100644 --- a/DuckDuckGo/Windows/View/WindowControllersManager.swift +++ b/DuckDuckGo/Windows/View/WindowControllersManager.swift @@ -38,6 +38,10 @@ final class WindowControllersManager: WindowControllersManagerProtocol { static let shared = WindowControllersManager(pinnedTabsManager: Application.appDelegate.pinnedTabsManager) + var activeViewController: MainViewController? { + lastKeyMainWindowController?.mainViewController + } + init(pinnedTabsManager: PinnedTabsManager) { self.pinnedTabsManager = pinnedTabsManager } @@ -52,7 +56,7 @@ final class WindowControllersManager: WindowControllersManagerProtocol { weak var lastKeyMainWindowController: MainWindowController? { didSet { if lastKeyMainWindowController != oldValue { - didChangeKeyWindowController.send(()) + didChangeKeyWindowController.send(lastKeyMainWindowController) } } } @@ -69,7 +73,7 @@ final class WindowControllersManager: WindowControllersManagerProtocol { return mainWindowController?.mainViewController.tabCollectionViewModel.selectedTab } - let didChangeKeyWindowController = PassthroughSubject() + let didChangeKeyWindowController = PassthroughSubject() let didRegisterWindowController = PassthroughSubject<(MainWindowController), Never>() let didUnregisterWindowController = PassthroughSubject<(MainWindowController), Never>() diff --git a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift index 6a3e6c6f7f5..3b5d39600d8 100644 --- a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift +++ b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift @@ -75,7 +75,7 @@ final class DuckDuckGoVPNApplication: NSApplication { self.delegate = _delegate #if DEBUG - if let token = accountManager.accessToken { + if accountManager.accessToken != nil { os_log(.error, log: .networkProtection, "🟢 VPN Agent found token") } else { os_log(.error, log: .networkProtection, "🔴 VPN Agent found no token") @@ -311,6 +311,9 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { }.eraseToAnyPublisher() let model = StatusBarMenuModel(vpnSettings: .init(defaults: .netP)) + let uiActionHandler = VPNUIActionHandler( + appLauncher: appLauncher, + proxySettings: proxySettings) return StatusBarMenu( model: model, @@ -318,7 +321,7 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { statusReporter: statusReporter, controller: tunnelController, iconProvider: iconProvider, - uiActionHandler: appLauncher, + uiActionHandler: uiActionHandler, menuItems: { [ StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuVPNSettings, action: { [weak self] in diff --git a/DuckDuckGoVPN/TunnelControllerIPCService.swift b/DuckDuckGoVPN/TunnelControllerIPCService.swift index 5052f99ca2c..c95c4fc0b1f 100644 --- a/DuckDuckGoVPN/TunnelControllerIPCService.swift +++ b/DuckDuckGoVPN/TunnelControllerIPCService.swift @@ -243,6 +243,9 @@ extension TunnelControllerIPCService: XPCServerInterface { break case .removeVPNConfiguration: try await uninstall(.configuration) + case .restartAdapter: + // Intentional no-op: handled by the extension + break case .uninstallVPN: try await uninstall(.all) case .disableConnectOnDemandAndShutDown: diff --git a/DuckDuckGoVPN/VPNUIActionHandler.swift b/DuckDuckGoVPN/VPNUIActionHandler.swift new file mode 100644 index 00000000000..dae739499c5 --- /dev/null +++ b/DuckDuckGoVPN/VPNUIActionHandler.swift @@ -0,0 +1,58 @@ +// +// VPNUIActionHandler.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import AppLauncher +import Foundation +import NetworkProtectionProxy +import NetworkProtectionUI +import VPNAppLauncher + +/// VPN Agent's UI action handler +/// +final class VPNUIActionHandler: VPNUIActionHandling { + + private let appLauncher: AppLauncher + private let proxySettings: TransparentProxySettings + + init(appLauncher: AppLauncher, proxySettings: TransparentProxySettings) { + self.appLauncher = appLauncher + self.proxySettings = proxySettings + } + + public func moveAppToApplications() async { +#if !APPSTORE && !DEBUG + try? await appLauncher.launchApp(withCommand: VPNAppLaunchCommand.moveAppToApplications) +#endif + } + + func setExclusion(_ exclude: Bool, forDomain domain: String) async { + proxySettings.setExclusion(exclude, forDomain: domain) + } + + public func shareFeedback() async { + try? await appLauncher.launchApp(withCommand: VPNAppLaunchCommand.shareFeedback) + } + + public func showVPNLocations() async { + try? await appLauncher.launchApp(withCommand: VPNAppLaunchCommand.showVPNLocations) + } + + public func showPrivacyPro() async { + try? await appLauncher.launchApp(withCommand: VPNAppLaunchCommand.showPrivacyPro) + } +} diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index 0da0593983e..abefa9639e6 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.1"), .package(path: "../SwiftUIExtensions"), .package(path: "../XPCHelper"), ], diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index 841f8ef5eb5..9bea4fce247 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -32,7 +32,7 @@ let package = Package( .library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.1"), .package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"), .package(path: "../AppLauncher"), .package(path: "../UDSHelper"), diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/FlowManagers/TCPFlowManager.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/FlowManagers/TCPFlowManager.swift index 882eb197341..edf987d2018 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/FlowManagers/TCPFlowManager.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/FlowManagers/TCPFlowManager.swift @@ -30,20 +30,35 @@ struct TCPFlowActor { } @TCPFlowActor -enum RemoteConnectionError: Error { +enum RemoteConnectionError: CustomNSError { case complete case cancelled case couldNotEstablishConnection(_ error: Error) case unhandledError(_ error: Error) + + nonisolated + var errorUserInfo: [String: Any] { + switch self { + case .complete, + .cancelled: + return [:] + case .couldNotEstablishConnection(let error), + .unhandledError(let error): + return [NSUnderlyingErrorKey: error as NSError] + + } + } } final class TCPFlowManager { private let flow: NEAppProxyTCPFlow private var connectionTask: Task? private var connection: NWConnection? + private let logger: Logger - init(flow: NEAppProxyTCPFlow) { + init(flow: NEAppProxyTCPFlow, logger: Logger) { self.flow = flow + self.logger = logger } deinit { @@ -67,10 +82,13 @@ final class TCPFlowManager { do { try await startDataCopyLoop(for: remoteConnection) + logger.log("🔴 Stopping proxy connection to \(remoteEndpoint, privacy: .public)") remoteConnection.cancel() flow.closeReadWithError(nil) flow.closeWriteWithError(nil) } catch { + logger.log("🔴 Stopping proxy connection to \(remoteEndpoint, privacy: .public) with error \(String(reflecting: error), privacy: .public)") + remoteConnection.cancel() flow.closeReadWithError(error) flow.closeWriteWithError(error) diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/IPC/TransparentProxyAppMessageHandler.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/IPC/TransparentProxyAppMessageHandler.swift index 12339a673d7..988ffd1f77f 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/IPC/TransparentProxyAppMessageHandler.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/IPC/TransparentProxyAppMessageHandler.swift @@ -18,14 +18,18 @@ import Foundation import OSLog // swiftlint:disable:this enforce_os_log_wrapper +import NetworkExtension /// Handles app messages /// final class TransparentProxyAppMessageHandler { private let settings: TransparentProxySettings + private let logger: Logger - init(settings: TransparentProxySettings) { + init(settings: TransparentProxySettings, logger: Logger) { + + self.logger = logger self.settings = settings } @@ -48,11 +52,13 @@ final class TransparentProxyAppMessageHandler { await withCheckedContinuation { continuation in var request: TransparentProxyRequest + logger.log("Handling app message: \(String(describing: message), privacy: .public)") + switch message { case .changeSetting(let change): - request = .changeSetting(change, responseHandler: { + request = .changeSetting(change) { continuation.resume(returning: nil) - }) + } } handle(request) diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Settings/TransparentProxySettings.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Settings/TransparentProxySettings.swift index db010ec2b5d..ba8d98c243b 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Settings/TransparentProxySettings.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Settings/TransparentProxySettings.swift @@ -79,16 +79,16 @@ public final class TransparentProxySettings { // MARK: - App routing rules logic - public func isBlocking(_ appIdentifier: String) -> Bool { + public func isBlocking(appIdentifier: String) -> Bool { appRoutingRules[appIdentifier] == .block } - public func isExcluding(_ appIdentifier: String) -> Bool { + public func isExcluding(appIdentifier: String) -> Bool { appRoutingRules[appIdentifier] == .exclude } public func toggleBlocking(for appIdentifier: String) { - if isBlocking(appIdentifier) { + if isBlocking(appIdentifier: appIdentifier) { appRoutingRules.removeValue(forKey: appIdentifier) } else { appRoutingRules[appIdentifier] = .block @@ -96,13 +96,43 @@ public final class TransparentProxySettings { } public func toggleExclusion(for appIdentifier: String) { - if isExcluding(appIdentifier) { + if isExcluding(appIdentifier: appIdentifier) { appRoutingRules.removeValue(forKey: appIdentifier) } else { appRoutingRules[appIdentifier] = .exclude } } + // MARK: - Domain Exclusions + + public func isExcluding(domain: String) -> Bool { + excludedDomains.contains(domain) + } + + public func setExclusion(_ exclude: Bool, forDomain domain: String) { + if exclude { + guard !isExcluding(domain: domain) else { + return + } + + excludedDomains.append(domain) + } else { + guard isExcluding(domain: domain) else { + return + } + + excludedDomains.removeAll { $0 == domain } + } + } + + public func toggleExclusion(domain: String) { + if isExcluding(domain: domain) { + excludedDomains.removeAll { $0 == domain } + } else { + excludedDomains.append(domain) + } + } + // MARK: - Snapshot support public func snapshot() -> TransparentProxySettingsSnapshot { diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/TransparentProxyProvider.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/TransparentProxyProvider.swift index 33b75fd73b9..c71dbc9ee18 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/TransparentProxyProvider.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/TransparentProxyProvider.swift @@ -16,6 +16,7 @@ // limitations under the License. // +import Combine import Foundation import NetworkExtension import NetworkProtection @@ -35,10 +36,10 @@ open class TransparentProxyProvider: NETransparentProxyProvider { static let dnsPort = 53 @TCPFlowActor - var tcpFlowManagers = Set() + private var tcpFlowManagers = Set() @UDPFlowActor - var udpFlowManagers = Set() + private var udpFlowManagers = Set() private let monitor = nw_path_monitor_create() var directInterface: nw_interface_t? @@ -46,6 +47,8 @@ open class TransparentProxyProvider: NETransparentProxyProvider { private let bMonitor = NWPathMonitor() var interface: NWInterface? + private var cancellables = Set() + public let configuration: Configuration public let settings: TransparentProxySettings @@ -54,8 +57,7 @@ open class TransparentProxyProvider: NETransparentProxyProvider { public var eventHandler: EventCallback? private let logger: Logger - - private lazy var appMessageHandler = TransparentProxyAppMessageHandler(settings: settings) + private let appMessageHandler: TransparentProxyAppMessageHandler // MARK: - Init @@ -63,10 +65,15 @@ open class TransparentProxyProvider: NETransparentProxyProvider { configuration: Configuration, logger: Logger) { + appMessageHandler = TransparentProxyAppMessageHandler(settings: settings, logger: logger) self.configuration = configuration self.logger = logger self.settings = settings + super.init() + + subscribeToSettings() + logger.debug("[+] \(String(describing: Self.self), privacy: .public)") } @@ -74,6 +81,21 @@ open class TransparentProxyProvider: NETransparentProxyProvider { logger.debug("[-] \(String(describing: Self.self), privacy: .public)") } + private func subscribeToSettings() { + settings.changePublisher.sink { change in + switch change { + case .appRoutingRules: + Task { + try await self.updateNetworkSettings() + } + case .excludedDomains: + Task { + try await self.updateNetworkSettings() + } + } + }.store(in: &cancellables) + } + private func loadProviderConfiguration() throws { guard configuration.loadSettingsFromProviderConfiguration else { return @@ -105,7 +127,7 @@ open class TransparentProxyProvider: NETransparentProxyProvider { return } - logger.log("Successfully Updated network settings: \(String(describing: error), privacy: .public))") + logger.log("Successfully Updated network settings: \(networkSettings.description, privacy: .public)") continuation.resume() } } @@ -116,35 +138,39 @@ open class TransparentProxyProvider: NETransparentProxyProvider { let networkSettings = NETransparentProxyNetworkSettings(tunnelRemoteAddress: "127.0.0.1") networkSettings.includedNetworkRules = [ - NENetworkRule(remoteNetwork: NWHostEndpoint(hostname: "127.0.0.1", port: ""), remotePrefix: 0, localNetwork: nil, localPrefix: 0, protocol: .any, direction: .outbound) + NENetworkRule(remoteNetwork: nil, remotePrefix: 0, localNetwork: nil, localPrefix: 0, protocol: .TCP, direction: .outbound), + NENetworkRule(remoteNetwork: nil, remotePrefix: 0, localNetwork: nil, localPrefix: 0, protocol: .UDP, direction: .outbound) ] + if isExcludedDomain("duckduckgo.com") { + networkSettings.includedNetworkRules?.append( + NENetworkRule(destinationHost: NWHostEndpoint(hostname: "duckduckgo.com", port: "443"), protocol: .any)) + } + return networkSettings } - override public func startProxy(options: [String: Any]?, - completionHandler: @escaping (Error?) -> Void) { + @MainActor + override open func startProxy(options: [String: Any]? = nil) async throws { eventHandler?(.startInitiated) - logger.log( - """ - Starting proxy\n - > configuration: \(String(describing: self.configuration), privacy: .public)\n - > settings: \(String(describing: self.settings), privacy: .public)\n - > options: \(String(describing: options), privacy: .public) - """) - do { - try loadProviderConfiguration() - } catch { - logger.error("Failed to load provider configuration, bailing out") - eventHandler?(.startFailure(error)) - completionHandler(error) - return - } + logger.log( + """ + Starting proxy\n + > configuration: \(String(describing: self.configuration), privacy: .public)\n + > settings: \(String(describing: self.settings), privacy: .public)\n + > options: \(String(describing: options), privacy: .public) + """) + + do { + try loadProviderConfiguration() + } catch { + logger.error("Failed to load provider configuration, bailing out") + throw error + } - Task { @MainActor in do { startMonitoringNetworkInterfaces() @@ -152,61 +178,82 @@ open class TransparentProxyProvider: NETransparentProxyProvider { logger.log("Proxy started successfully") isRunning = true eventHandler?(.startSuccess) - completionHandler(nil) } catch { let error = StartError.failedToUpdateNetworkSettings(underlyingError: error) logger.error("Proxy failed to start \(String(reflecting: error), privacy: .public)") - eventHandler?(.startFailure(error)) - completionHandler(error) + throw error } + } catch { + eventHandler?(.startFailure(error)) + throw error } } - override public func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { + @MainActor + open override func stopProxy(with reason: NEProviderStopReason) async { + logger.log("Stopping proxy with reason: \(String(reflecting: reason), privacy: .public)") - Task { @MainActor in - stopMonitoringNetworkInterfaces() - isRunning = false - completionHandler() - } + stopMonitoringNetworkInterfaces() + isRunning = false } + @MainActor override public func sleep(completionHandler: @escaping () -> Void) { - Task { @MainActor in - stopMonitoringNetworkInterfaces() - logger.log("The proxy is now sleeping") - completionHandler() - } + stopMonitoringNetworkInterfaces() + logger.log("The proxy is now sleeping") + completionHandler() } + @MainActor override public func wake() { - Task { @MainActor in - logger.log("The proxy is now awake") - startMonitoringNetworkInterfaces() - } + logger.log("The proxy is now awake") + startMonitoringNetworkInterfaces() + } + + private func logFlowMessage(_ flow: NEAppProxyFlow, level: OSLogType, message: String) { + logger.log( + level: level, + """ + \(message, privacy: .public) + - remote: \(String(reflecting: flow.remoteHostname), privacy: .public) + - flowID: \(String(reflecting: flow.metaData.filterFlowIdentifier?.uuidString), privacy: .public) + - appID: \(String(reflecting: flow.metaData.sourceAppSigningIdentifier), privacy: .public) + """ + ) + } + + private func logNewTCPFlow(_ flow: NEAppProxyFlow) { + logFlowMessage( + flow, + level: .default, + message: "[TCP] New flow: \(String(reflecting: flow))") + } + + private func logFlowHandlingFailure(_ flow: NEAppProxyFlow, message: String) { + logFlowMessage( + flow, + level: .error, + message: "[TCP] Failure handling flow: \(message)") } override public func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool { + logNewTCPFlow(flow) + guard let flow = flow as? NEAppProxyTCPFlow else { - logger.info("Expected a TCP flow, but got something else. We're ignoring it.") + logFlowHandlingFailure(flow, message: "Expected a TCP flow, but got something else. We're ignoring the flow.") return false } - guard let remoteEndpoint = flow.remoteEndpoint as? NWHostEndpoint, - !isDnsServer(remoteEndpoint) else { + guard let remoteEndpoint = flow.remoteEndpoint as? NWHostEndpoint else { + logFlowHandlingFailure(flow, message: "No remote endpoint. We're ignoring the flow.") return false } - let printableRemote = flow.remoteHostname ?? (flow.remoteEndpoint as? NWHostEndpoint)?.hostname ?? "unknown" - - logger.debug( - """ - [TCP] New flow: \(String(describing: flow), privacy: .public) - - remote: \(printableRemote, privacy: .public) - - flowID: \(String(describing: flow.metaData.filterFlowIdentifier?.uuidString), privacy: .public) - - appID: \(String(describing: flow.metaData.sourceAppSigningIdentifier), privacy: .public) - """) + guard !isDnsServer(remoteEndpoint) else { + logFlowHandlingFailure(flow, message: "DNS resolver endpoint. We're ignoring the flow.") + return false + } guard let interface else { logger.error("[TCP: \(String(describing: flow), privacy: .public)] Expected an interface to exclude traffic through") @@ -235,11 +282,13 @@ open class TransparentProxyProvider: NETransparentProxyProvider { flow.networkInterface = directInterface Task { @TCPFlowActor in - let flowManager = TCPFlowManager(flow: flow) + let flowManager = TCPFlowManager(flow: flow, logger: logger) tcpFlowManagers.insert(flowManager) try? await flowManager.start(interface: interface) tcpFlowManagers.remove(flowManager) + + logFlowMessage(flow, level: .default, message: "[TCP] Flow completed") } return true diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Animation/AnimationConstants.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Animation/AnimationConstants.swift new file mode 100644 index 00000000000..552e5dc433a --- /dev/null +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Animation/AnimationConstants.swift @@ -0,0 +1,23 @@ +// +// AnimationConstants.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +struct AnimationConstants { + static let highlightAnimationStepSpeed = 0.05 +} diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/StatusBarMenu.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/StatusBarMenu.swift index 9d541e976cb..53e2a245994 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/StatusBarMenu.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/StatusBarMenu.swift @@ -37,7 +37,7 @@ public final class StatusBarMenu: NSObject { private let controller: TunnelController private let statusReporter: NetworkProtectionStatusReporter private let onboardingStatusPublisher: OnboardingStatusPublisher - private let uiActionHandler: VPNUIActionHandler + private let uiActionHandler: VPNUIActionHandling private let menuItems: () -> [MenuItem] private let agentLoginItem: LoginItem? private let isMenuBarStatusView: Bool @@ -64,7 +64,7 @@ public final class StatusBarMenu: NSObject { statusReporter: NetworkProtectionStatusReporter, controller: TunnelController, iconProvider: IconProvider, - uiActionHandler: VPNUIActionHandler, + uiActionHandler: VPNUIActionHandling, menuItems: @escaping () -> [MenuItem], agentLoginItem: LoginItem?, isMenuBarStatusView: Bool, @@ -108,7 +108,9 @@ public final class StatusBarMenu: NSObject { return } - togglePopover(isOptionKeyPressed: isOptionKeyPressed) + Task { @MainActor in + togglePopover(isOptionKeyPressed: isOptionKeyPressed) + } } private func subscribeToIconUpdates() { @@ -122,6 +124,7 @@ public final class StatusBarMenu: NSObject { // MARK: - Popover + @MainActor private func togglePopover(isOptionKeyPressed: Bool) { if let popover, popover.isShown { popover.close() @@ -131,19 +134,33 @@ public final class StatusBarMenu: NSObject { return } - popover = NetworkProtectionPopover(controller: controller, - onboardingStatusPublisher: onboardingStatusPublisher, - statusReporter: statusReporter, - uiActionHandler: uiActionHandler, - menuItems: menuItems, - agentLoginItem: agentLoginItem, - isMenuBarStatusView: isMenuBarStatusView, - userDefaults: userDefaults, - locationFormatter: locationFormatter, - uninstallHandler: uninstallHandler) + let siteTroubleshootingViewModel = SiteTroubleshootingView.Model( + featureFlagPublisher: Just(false).eraseToAnyPublisher(), + connectionStatusPublisher: Just(NetworkProtection.ConnectionStatus.disconnected).eraseToAnyPublisher(), + siteTroubleshootingInfoPublisher: Just(SiteTroubleshootingInfo?(nil)).eraseToAnyPublisher(), + uiActionHandler: uiActionHandler) + + let debugInformationViewModel = DebugInformationViewModel(showDebugInformation: isOptionKeyPressed) + + let statusViewModel = NetworkProtectionStatusView.Model( + controller: controller, + onboardingStatusPublisher: onboardingStatusPublisher, + statusReporter: statusReporter, + uiActionHandler: uiActionHandler, + menuItems: menuItems, + agentLoginItem: agentLoginItem, + isMenuBarStatusView: isMenuBarStatusView, + userDefaults: userDefaults, + locationFormatter: locationFormatter, + uninstallHandler: uninstallHandler) + + popover = NetworkProtectionPopover( + statusViewModel: statusViewModel, + statusReporter: statusReporter, + siteTroubleshootingViewModel: siteTroubleshootingViewModel, + debugInformationViewModel: debugInformationViewModel) popover?.behavior = .transient - popover?.setShowsDebugInformation(isOptionKeyPressed) popover?.show(relativeTo: button.bounds, of: button, preferredEdge: .minY) } } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionAsset.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionAsset.swift index a8288b7dbdc..e09c9c93a61 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionAsset.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionAsset.swift @@ -51,4 +51,7 @@ public enum NetworkProtectionAsset: String, CaseIterable { // Images: case allowSysexScreenshot = "allow-sysex-screenshot" case allowSysexScreenshotBigSur = "allow-sysex-screenshot-bigsur" + + // Accordion View + case accordionViewCheckmark = "Check-16D" } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift index 0d1837d6e89..a6ba7befa5f 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift @@ -45,34 +45,21 @@ public final class NetworkProtectionPopover: NSPopover { public typealias MenuItem = NetworkProtectionStatusView.Model.MenuItem - private let debugInformationPublisher = CurrentValueSubject(false) private let statusReporter: NetworkProtectionStatusReporter - private let model: NetworkProtectionStatusView.Model + private let debugInformationViewModel: DebugInformationViewModel + private let siteTroubleshootingViewModel: SiteTroubleshootingView.Model + private let statusViewModel: NetworkProtectionStatusView.Model private var appLifecycleCancellables = Set() - public required init(controller: TunnelController, - onboardingStatusPublisher: OnboardingStatusPublisher, + public required init(statusViewModel: NetworkProtectionStatusView.Model, statusReporter: NetworkProtectionStatusReporter, - uiActionHandler: VPNUIActionHandler, - menuItems: @escaping () -> [MenuItem], - agentLoginItem: LoginItem?, - isMenuBarStatusView: Bool, - userDefaults: UserDefaults, - locationFormatter: VPNLocationFormatting, - uninstallHandler: @escaping () async -> Void) { + siteTroubleshootingViewModel: SiteTroubleshootingView.Model, + debugInformationViewModel: DebugInformationViewModel) { self.statusReporter = statusReporter - self.model = NetworkProtectionStatusView.Model(controller: controller, - onboardingStatusPublisher: onboardingStatusPublisher, - statusReporter: statusReporter, - debugInformationPublisher: debugInformationPublisher.eraseToAnyPublisher(), - uiActionHandler: uiActionHandler, - menuItems: menuItems, - agentLoginItem: agentLoginItem, - isMenuBarStatusView: isMenuBarStatusView, - userDefaults: userDefaults, - locationFormatter: locationFormatter, - uninstallHandler: uninstallHandler) + self.debugInformationViewModel = debugInformationViewModel + self.siteTroubleshootingViewModel = siteTroubleshootingViewModel + self.statusViewModel = statusViewModel super.init() @@ -88,7 +75,11 @@ public final class NetworkProtectionPopover: NSPopover { } private func setupContentController() { - let view = NetworkProtectionStatusView(model: self.model).environment(\.dismiss, { [weak self] in + let view = NetworkProtectionStatusView() + .environmentObject(debugInformationViewModel) + .environmentObject(siteTroubleshootingViewModel) + .environmentObject(statusViewModel) + .environment(\.dismiss, { [weak self] in self?.close() }).fixedSize() @@ -106,7 +97,7 @@ public final class NetworkProtectionPopover: NSPopover { NotificationCenter .default .publisher(for: NSApplication.didBecomeActiveNotification) - .sink { [weak self] _ in self?.model.refreshLoginItemStatus() } + .sink { [weak self] _ in self?.statusViewModel.refreshLoginItemStatus() } .store(in: &appLifecycleCancellables) NotificationCenter @@ -117,20 +108,14 @@ public final class NetworkProtectionPopover: NSPopover { } private func closePopoverIfOnboarded() { - if self.model.onboardingStatus == .completed { + if self.statusViewModel.onboardingStatus == .completed { self.close() } } override public func show(relativeTo positioningRect: NSRect, of positioningView: NSView, preferredEdge: NSRectEdge) { statusReporter.forceRefresh() - model.refreshLoginItemStatus() + statusViewModel.refreshLoginItemStatus() super.show(relativeTo: positioningRect, of: positioningView, preferredEdge: preferredEdge) } - - // MARK: - Debug Information - - func setShowsDebugInformation(_ showsDebugInformation: Bool) { - debugInformationPublisher.send(showsDebugInformation) - } } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Check-16D.pdf b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Check-16D.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9a1b194b77f149b7545ffb923bd8fd91c59225a6 GIT binary patch literal 1525 zcmZux+iu%141L#E@TEZeP)C$RU4Wv%nqDw$!@6{D#U8vwO*16+7P~{YuP^C1mnIQ{ zSUx6scqox4_t&@QSOldIG}J$TDS(R$7~H(JcMomZ=G7Z^k8ugQh)(l@%gfbI*&V=5nD1*ZJ>koJV(8Fnrj38#n5Y8r&dE8-;~1Fo#}m&NsWw zH&bvPHX$$)6WIjgh1!@MZkln$pD9I61itWr$XO5<>mq7|z+}YYfXUDp6G@<;Q$T?n z8H$EIqhV_gW5r;ICWgcy1=QY%U35`vflzB7yg)rE6(MLFHM?%GO(JvktZYFm-N-H> zdF1p=ku)YpEE64BCY!UJc2?+gktinZz!t_^9l6@VpNt?b`D9&(aIDCzwg^^-*kc+E zTO~rDVi$=pCUAvL&a$8IY2w)8x1X0}i>A;PqnILB$7;4+2x_9^iV7Mc8s|YUV=<*} zM+P15u!zZV`hqb{NW@HxlJ@~wt|HRn=_+k3YE8c@4h*`<-EMUruume94npc~!r{Bj1be zM((sC`ZcuOts{+cQ@vw_l!l;I^5q{qktJZbU&vLF z1w2^#6*x~>TPOwAvj?TH2O)<2Sll?z>|CzJz25-4+J2_~zRVODmUvJ+4uv17W literal 0 HcmV?d00001 diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Contents.json b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Contents.json new file mode 100644 index 00000000000..20caa8ff8a7 --- /dev/null +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Check-16D.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/AccordionView.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/AccordionView.swift new file mode 100644 index 00000000000..eb1cd4ce8e3 --- /dev/null +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/AccordionView.swift @@ -0,0 +1,119 @@ +// +// AccordionView.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import SwiftUI + +struct SideMenuStyle: MenuStyle { + func makeBody(configuration: Configuration) -> some View { + Menu(configuration) + .menuStyle(DefaultMenuStyle()) + .frame(maxWidth: .infinity, alignment: .leading) // Align the menu to the leading edge + } +} + +struct AccordionView: View { + @Environment(\.colorScheme) private var colorScheme + private var label: (Bool) -> Label + private let submenu: () -> Submenu + + private var highlightAnimationStepSpeed = AnimationConstants.highlightAnimationStepSpeed + + @State private var isHovered = false + @State private var highlightOverride: Bool? + @State private var showSubmenu = false + + private var isHighlighted: Bool { + highlightOverride ?? isHovered + } + + init(@ViewBuilder label: @escaping (Bool) -> Label, + @ViewBuilder submenu: @escaping () -> Submenu) { + + self.label = label + self.submenu = submenu + } + + var body: some View { + content + .frame(maxWidth: .infinity, alignment: .leading) + .contentShape(Rectangle()) + .cornerRadius(4) + } + + private func buttonBackground(highlighted: Bool) -> some View { + if highlighted { + return AnyView( + VisualEffectView(material: .selection, blendingMode: .withinWindow, state: .active, isEmphasized: true)) + } else { + return AnyView(Color.clear) + } + } + + private var content: some View { + VStack { + Button(action: { + buttonTapped() + }) { + HStack { + label(isHovered) + Spacer() + + if showSubmenu { + Image(systemName: "chevron.down") // Chevron pointing right + .foregroundColor(.gray) + } else { + Image(systemName: "chevron.right") // Chevron pointing right + .foregroundColor(.gray) + } + }.padding([.top, .bottom], 3) + .padding([.leading, .trailing], 9) + }.buttonStyle(PlainButtonStyle()) + .frame(maxWidth: .infinity, alignment: .leading) + .background( + buttonBackground(highlighted: isHighlighted) + ) + .onTapGesture { + buttonTapped() + } + .onHover { hovering in + isHovered = hovering + } + + if showSubmenu { + VStack { + submenu() + .frame(maxWidth: .infinity, alignment: .leading) + } + } + } + } + + private func buttonTapped() { + highlightOverride = false + + DispatchQueue.main.asyncAfter(deadline: .now() + highlightAnimationStepSpeed) { + highlightOverride = true + + DispatchQueue.main.asyncAfter(deadline: .now() + highlightAnimationStepSpeed) { + highlightOverride = nil + showSubmenu.toggle() + } + } + } +} diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemButton.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemButton.swift index 59e814b53c9..e8270c4a9fa 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemButton.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemButton.swift @@ -27,7 +27,7 @@ struct MenuItemButton: View { private let textColor: Color private let action: () async -> Void - private let highlightAnimationStepSpeed = 0.05 + private let highlightAnimationStepSpeed = AnimationConstants.highlightAnimationStepSpeed @State private var isHovered = false @State private var animatingTap = false diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemCustomButton.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemCustomButton.swift index cdd8bd79c87..dbef97ab235 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemCustomButton.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemCustomButton.swift @@ -24,7 +24,7 @@ struct MenuItemCustomButton: View { private var label: (Bool) -> Label private let action: () async -> Void - private let highlightAnimationStepSpeed = 0.05 + private let highlightAnimationStepSpeed = AnimationConstants.highlightAnimationStepSpeed @State private var isHovered = false @State private var animatingTap = false diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandler/VPNUIActionHandler.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandling/VPNUIActionHandling.swift similarity index 84% rename from LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandler/VPNUIActionHandler.swift rename to LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandling/VPNUIActionHandling.swift index 76ff99d563c..b57f8bcc555 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandler/VPNUIActionHandler.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandling/VPNUIActionHandling.swift @@ -1,5 +1,5 @@ // -// VPNUIActionHandler.swift +// VPNUIActionHandling.swift // // Copyright © 2024 DuckDuckGo. All rights reserved. // @@ -18,8 +18,9 @@ import Foundation -public protocol VPNUIActionHandler { +public protocol VPNUIActionHandling { func moveAppToApplications() async + func setExclusion(_ exclude: Bool, forDomain domain: String) async func shareFeedback() async func showPrivacyPro() async func showVPNLocations() async diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationView.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationView.swift index 34ea0bb2b17..82c30728d49 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationView.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationView.swift @@ -31,25 +31,21 @@ public struct DebugInformationView: View { /// The view model that this instance will use. /// - @ObservedObject var model: DebugInformationViewModel - - // MARK: - Initializers - - public init(model: DebugInformationViewModel) { - self.model = model - } + @EnvironmentObject var model: DebugInformationViewModel // MARK: - View Contents public var body: some View { - Group { - VStack(alignment: .leading, spacing: 0) { - informationRow(title: "Bundle Path", details: model.bundlePath) - informationRow(title: "Version", details: model.version) + if model.showDebugInformation { + Group { + VStack(alignment: .leading, spacing: 0) { + informationRow(title: "Bundle Path", details: model.bundlePath) + informationRow(title: "Version", details: model.version) + } + + Divider() + .padding(EdgeInsets(top: 5, leading: 9, bottom: 5, trailing: 9)) } - - Divider() - .padding(EdgeInsets(top: 5, leading: 9, bottom: 5, trailing: 9)) } } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationViewModel.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationViewModel.swift index f8433a1c28d..d8186a65c72 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationViewModel.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationViewModel.swift @@ -21,15 +21,19 @@ import Foundation import NetworkProtection import SwiftUI -@MainActor public final class DebugInformationViewModel: ObservableObject { - var bundlePath: String - var version: String + let showDebugInformation: Bool + let bundlePath: String + let version: String + private var cancellables = Set() // MARK: - Initialization & Deinitialization - public init(bundle: Bundle = .main) { + public init(showDebugInformation: Bool, + bundle: Bundle = .main) { + + self.showDebugInformation = showDebugInformation bundlePath = bundle.bundlePath // swiftlint:disable:next force_cast diff --git a/LocalPackages/NetworkProtectionMac/Sources/VPNAppLauncher/AppLauncher+VPNUIActionHandler.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingInfo.swift similarity index 50% rename from LocalPackages/NetworkProtectionMac/Sources/VPNAppLauncher/AppLauncher+VPNUIActionHandler.swift rename to LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingInfo.swift index ed491f743b2..704cb2731e7 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/VPNAppLauncher/AppLauncher+VPNUIActionHandler.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingInfo.swift @@ -1,5 +1,5 @@ // -// AppLauncher+VPNUIActionHandler.swift +// SiteTroubleshootingInfo.swift // // Copyright © 2024 DuckDuckGo. All rights reserved. // @@ -16,25 +16,21 @@ // limitations under the License. // -import AppLauncher +import AppKit import Foundation -import NetworkProtectionUI -extension AppLauncher: VPNUIActionHandler { +public struct SiteTroubleshootingInfo { + public let icon: NSImage + public let domain: String + public let excluded: Bool - public func moveAppToApplications() async { - try? await launchApp(withCommand: VPNAppLaunchCommand.moveAppToApplications) + public init(icon: NSImage?, domain: String, excluded: Bool) { + self.icon = icon ?? NSImage(systemSymbolName: "globe", accessibilityDescription: nil)! + self.domain = domain + self.excluded = excluded } +} - public func shareFeedback() async { - try? await launchApp(withCommand: VPNAppLaunchCommand.shareFeedback) - } +extension SiteTroubleshootingInfo: Equatable { - public func showVPNLocations() async { - try? await launchApp(withCommand: VPNAppLaunchCommand.showVPNLocations) - } - - public func showPrivacyPro() async { - try? await launchApp(withCommand: VPNAppLaunchCommand.showPrivacyPro) - } } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingView.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingView.swift new file mode 100644 index 00000000000..ed7580369ba --- /dev/null +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingView.swift @@ -0,0 +1,97 @@ +// +// SiteTroubleshootingView.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine +import Foundation +import SwiftUI + +fileprivate extension View { + func applyCurrentSiteAttributes() -> some View { + font(.system(size: 13, weight: .regular, design: .default)) + } +} + +public struct SiteTroubleshootingView: View { + + @EnvironmentObject var model: Model + + // MARK: - View Contents + + public var body: some View { + if model.isFeatureEnabled, + let siteInfo = model.siteInfo { + siteTroubleshootingView(siteInfo) + } else { + EmptyView() + } + } + + private func siteTroubleshootingView(_ siteInfo: SiteTroubleshootingInfo) -> some View { + Group { + AccordionView { _ in + Image(nsImage: siteInfo.icon) + .resizable() + .frame(width: 16, height: 16) + .clipShape(RoundedRectangle(cornerRadius: 3.0)) + Text("\(siteInfo.domain) issues?") + .applyCurrentSiteAttributes() + } submenu: { + VStack { + MenuItemCustomButton { + model.setExclusion(true, forDomain: siteInfo.domain) + } label: { _ in + HStack { + if siteInfo.excluded { + Image(.accordionViewCheckmark) + .resizable() + .font(.system(size: 13)) + .frame(width: 16, height: 16) + .applyCurrentSiteAttributes() + } else { + Rectangle() + .fill(Color.clear) + .frame(width: 16, height: 16) + } + Text("Exclude from VPN") + } + } + + MenuItemCustomButton { + model.setExclusion(false, forDomain: siteInfo.domain) + } label: { _ in + if !siteInfo.excluded { + Image(.accordionViewCheckmark) + .resizable() + .font(.system(size: 13)) + .frame(width: 16, height: 16) + } else { + Rectangle() + .fill(Color.clear) + .frame(width: 16, height: 16) + } + + Text("Route through VPN") + } + } + } + + Divider() + .padding(EdgeInsets(top: 5, leading: 9, bottom: 5, trailing: 9)) + } + } +} diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingViewModel.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingViewModel.swift new file mode 100644 index 00000000000..b026feed85c --- /dev/null +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingViewModel.swift @@ -0,0 +1,88 @@ +// +// SiteTroubleshootingViewModel.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine +import Foundation +import NetworkProtection + +extension SiteTroubleshootingView { + + public final class Model: ObservableObject { + + @Published + private(set) var isFeatureEnabled = false + + @Published + private(set) var connectionStatus: ConnectionStatus = .disconnected + + @Published + private var internalSiteInfo: SiteTroubleshootingInfo? + + var siteInfo: SiteTroubleshootingInfo? { + guard case .connected = connectionStatus else { + return nil + } + + return internalSiteInfo + } + + private let uiActionHandler: VPNUIActionHandling + private var cancellables = Set() + + public init(featureFlagPublisher: AnyPublisher, + connectionStatusPublisher: AnyPublisher, + siteTroubleshootingInfoPublisher: AnyPublisher, + uiActionHandler: VPNUIActionHandling) { + + self.uiActionHandler = uiActionHandler + + subscribeToConnectionStatusChanges(connectionStatusPublisher) + subscribeToSiteTroubleshootingInfoChanges(siteTroubleshootingInfoPublisher) + subscribeToFeatureFlagChanges(featureFlagPublisher) + } + + private func subscribeToConnectionStatusChanges(_ publisher: AnyPublisher) { + + publisher + .receive(on: DispatchQueue.main) + .assign(to: \.connectionStatus, onWeaklyHeld: self) + .store(in: &cancellables) + } + + private func subscribeToSiteTroubleshootingInfoChanges(_ publisher: AnyPublisher) { + + publisher + .receive(on: DispatchQueue.main) + .assign(to: \.internalSiteInfo, onWeaklyHeld: self) + .store(in: &cancellables) + } + + private func subscribeToFeatureFlagChanges(_ publisher: AnyPublisher) { + publisher + .receive(on: DispatchQueue.main) + .assign(to: \.isFeatureEnabled, onWeaklyHeld: self) + .store(in: &cancellables) + } + + func setExclusion(_ exclude: Bool, forDomain domain: String) { + Task { @MainActor in + await uiActionHandler.setExclusion(exclude, forDomain: domain) + } + } + } +} diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift index 39a63eec043..22562a36ddc 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift @@ -38,13 +38,7 @@ public struct NetworkProtectionStatusView: View { /// The view model that this instance will use. /// - @ObservedObject var model: Model - - // MARK: - Initializers - - public init(model: Model) { - self.model = model - } + @EnvironmentObject var model: Model // MARK: - View Contents @@ -74,10 +68,8 @@ public struct NetworkProtectionStatusView: View { TunnelControllerView(model: model.tunnelControllerViewModel) .disabled(model.tunnelControllerViewDisabled) - if model.showDebugInformation { - DebugInformationView(model: DebugInformationViewModel()) - .transition(.slide) - } + DebugInformationView() + .transition(.slide) bottomMenuView() } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift index 8c126a81422..835078e15bc 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift @@ -73,15 +73,6 @@ extension NetworkProtectionStatusView { /// private let statusReporter: NetworkProtectionStatusReporter - /// The debug information publisher - /// - private let debugInformationPublisher: AnyPublisher - - /// Whether we're showing debug information - /// - @Published - var showDebugInformation: Bool - public let agentLoginItem: LoginItem? private let isMenuBarStatusView: Bool @@ -95,7 +86,7 @@ extension NetworkProtectionStatusView { /// private let runLoopMode: RunLoop.Mode? - private let uiActionHandler: VPNUIActionHandler + private let uiActionHandler: VPNUIActionHandling private let uninstallHandler: () async -> Void @@ -114,8 +105,7 @@ extension NetworkProtectionStatusView { public init(controller: TunnelController, onboardingStatusPublisher: OnboardingStatusPublisher, statusReporter: NetworkProtectionStatusReporter, - debugInformationPublisher: AnyPublisher, - uiActionHandler: VPNUIActionHandler, + uiActionHandler: VPNUIActionHandling, menuItems: @escaping () -> [MenuItem], agentLoginItem: LoginItem?, isMenuBarStatusView: Bool, @@ -127,7 +117,6 @@ extension NetworkProtectionStatusView { self.tunnelController = controller self.onboardingStatusPublisher = onboardingStatusPublisher self.statusReporter = statusReporter - self.debugInformationPublisher = debugInformationPublisher self.menuItems = menuItems self.agentLoginItem = agentLoginItem self.isMenuBarStatusView = isMenuBarStatusView @@ -147,7 +136,6 @@ extension NetworkProtectionStatusView { lastTunnelErrorMessage = statusReporter.connectionErrorObserver.recentValue lastControllerErrorMessage = statusReporter.controllerErrorMessageObserver.recentValue knownFailure = statusReporter.knownFailureObserver.recentValue - showDebugInformation = false // Particularly useful when unit testing with an initial status of our choosing. subscribeToStatusChanges() @@ -155,7 +143,6 @@ extension NetworkProtectionStatusView { subscribeToTunnelErrorMessages() subscribeToControllerErrorMessages() subscribeToKnownFailures() - subscribeToDebugInformationChanges() refreshLoginItemStatus() onboardingStatusPublisher @@ -255,14 +242,6 @@ extension NetworkProtectionStatusView { .store(in: &cancellables) } - private func subscribeToDebugInformationChanges() { - debugInformationPublisher - .removeDuplicates() - .receive(on: DispatchQueue.main) - .assign(to: \.showDebugInformation, onWeaklyHeld: self) - .store(in: &cancellables) - } - // MARK: - Connection Status: Errors @Published diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerView.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerView.swift index 3ef0d01d82f..96b5cab49ec 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerView.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerView.swift @@ -32,6 +32,10 @@ fileprivate extension Font { .system(size: 13, weight: .regular, design: .default) } + static var currentSite: Font { + .system(size: 13, weight: .regular, design: .default) + } + static var location: Font { .system(size: 13, weight: .regular, design: .default) } @@ -102,6 +106,10 @@ fileprivate extension View { .foregroundColor(Color(.defaultText)) } + func applyCurrentSiteAttributes() -> some View { + font(.NetworkProtection.currentSite) + } + func applyLocationAttributes() -> some View { font(.NetworkProtection.location) } @@ -172,6 +180,8 @@ public struct TunnelControllerView: View { Divider() .padding(EdgeInsets(top: 5, leading: 9, bottom: 5, trailing: 9)) + SiteTroubleshootingView() + locationView() if model.showServerDetails { diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerViewModel.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerViewModel.swift index 08cc7614e78..19d4dd5ee78 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerViewModel.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerViewModel.swift @@ -57,7 +57,6 @@ public final class TunnelControllerViewModel: ObservableObject { private let statusReporter: NetworkProtectionStatusReporter private let vpnSettings: VPNSettings - private let locationFormatter: VPNLocationFormatting private static let byteCountFormatter: ByteCountFormatter = { @@ -67,7 +66,12 @@ public final class TunnelControllerViewModel: ObservableObject { return formatter }() - private let uiActionHandler: VPNUIActionHandler + private let uiActionHandler: VPNUIActionHandling + + // MARK: - Environment + + @EnvironmentObject + private var siteTroubleshootingViewModel: SiteTroubleshootingView.Model // MARK: - Misc @@ -91,7 +95,7 @@ public final class TunnelControllerViewModel: ObservableObject { runLoopMode: RunLoop.Mode? = nil, vpnSettings: VPNSettings, locationFormatter: VPNLocationFormatting, - uiActionHandler: VPNUIActionHandler) { + uiActionHandler: VPNUIActionHandling) { self.tunnelController = controller self.onboardingStatusPublisher = onboardingStatusPublisher @@ -531,11 +535,13 @@ public final class TunnelControllerViewModel: ObservableObject { } } +#if !APPSTORE && !DEBUG func moveToApplications() { Task { @MainActor in await uiActionHandler.moveAppToApplications() } } +#endif } extension DataVolume { diff --git a/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/MockVPNUIActionHandler/MockVPNUIActionHandler.swift b/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/MockVPNUIActionHandler/MockVPNUIActionHandler.swift index 5e0240ca3db..c8d60cf9ede 100644 --- a/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/MockVPNUIActionHandler/MockVPNUIActionHandler.swift +++ b/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/MockVPNUIActionHandler/MockVPNUIActionHandler.swift @@ -19,7 +19,10 @@ import Foundation import NetworkProtectionUI -public final class MockVPNUIActionHandler: VPNUIActionHandler { +public final class MockVPNUIActionHandler: VPNUIActionHandling { + public func setExclusion(_ exclude: Bool, forDomain domain: String) async { + // placeholder + } public func moveAppToApplications() async { // placeholder diff --git a/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionAssetTests.swift b/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionAssetTests.swift index b49d24d5b4e..345050aba41 100644 --- a/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionAssetTests.swift +++ b/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionAssetTests.swift @@ -49,7 +49,8 @@ final class NetworkProtectionAssetTests: XCTestCase { .statusbarBrandedVPNOffIcon: "statusbar-branded-vpn-off", .statusbarBrandedVPNIssueIcon: "statusbar-branded-vpn-issue", .allowSysexScreenshot: "allow-sysex-screenshot", - .allowSysexScreenshotBigSur: "allow-sysex-screenshot-bigsur" + .allowSysexScreenshotBigSur: "allow-sysex-screenshot-bigsur", + .accordionViewCheckmark: "Check-16D" ] XCTAssertEqual(assetsAndExpectedRawValues.count, NetworkProtectionAsset.allCases.count) diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index 6e9ed1cd74a..b75fff50610 100644 --- a/LocalPackages/SubscriptionUI/Package.swift +++ b/LocalPackages/SubscriptionUI/Package.swift @@ -12,7 +12,7 @@ let package = Package( targets: ["SubscriptionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.1"), .package(path: "../SwiftUIExtensions") ], targets: [ diff --git a/UnitTests/NavigationBar/View/NavigationBarPopoversTests.swift b/UnitTests/NavigationBar/View/NavigationBarPopoversTests.swift index d2982ee38ca..b1b050b5e81 100644 --- a/UnitTests/NavigationBar/View/NavigationBarPopoversTests.swift +++ b/UnitTests/NavigationBar/View/NavigationBarPopoversTests.swift @@ -27,6 +27,7 @@ final class NavigationBarPopoversTests: XCTestCase { private var sut: NavigationBarPopovers! private var autofillPopoverPresenter: MockAutofillPopoverPresenter! + @MainActor override func setUpWithError() throws { autofillPopoverPresenter = MockAutofillPopoverPresenter() sut = NavigationBarPopovers(networkProtectionPopoverManager: NetPPopoverManagerMock(), autofillPopoverPresenter: autofillPopoverPresenter) From cbe237ec77c0606fe246b0bb1a39ab8a40e9eae1 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Tue, 6 Aug 2024 11:02:40 +0200 Subject: [PATCH 17/32] Disables a flaky test --- .../DataBrokerProtectionMigrationsFeatureFlaggerTests.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionMigrationsFeatureFlaggerTests.swift b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionMigrationsFeatureFlaggerTests.swift index 9dcc513e7f1..15cdea5d31e 100644 --- a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionMigrationsFeatureFlaggerTests.swift +++ b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionMigrationsFeatureFlaggerTests.swift @@ -157,6 +157,7 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { XCTAssertTrue(result) } + /* DISABLED(flaky) REF: https://app.asana.com/0/1203108348835387/1207987874156874/f func testAverageCalculatedRandomNumberAssignmentIsBetween9And11Percent() { // Given var percentages: [Double] = [] @@ -186,4 +187,5 @@ final class DataBrokerProtectionMigrationsFeatureFlaggerTests: XCTestCase { let average = sum / Double(percentages.count) XCTAssert(average > 9.0 && average < 11.0) } + */ } From 02caf5ec1ce7cae2f736e106771afb0950664ab0 Mon Sep 17 00:00:00 2001 From: Tom Strba <57389842+tomasstrba@users.noreply.github.com> Date: Tue, 6 Aug 2024 12:43:29 +0200 Subject: [PATCH 18/32] Release notes trusted indicator changed & Close button fix for dark mode (#3041) Task/Issue URL: https://app.asana.com/0/72649045549333/1207907199406205/f https://app.asana.com/0/1148564399326804/1207905046877700/f Tech Design URL: CC: **Description**: Release notes trusted indicator changed & Close button fix for dark mode --- .../ReleaseNotesIndicator.imageset/Contents.json | 12 ++++++++++++ .../Document-Color-16.pdf | Bin 0 -> 1327 bytes DuckDuckGo/Tab/ViewModel/TabViewModel.swift | 2 +- DuckDuckGo/Updates/UpdateController.swift | 4 ++-- .../Contents.json | 3 +++ 5 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 DuckDuckGo/Assets.xcassets/Images/ReleaseNotesIndicator.imageset/Contents.json create mode 100644 DuckDuckGo/Assets.xcassets/Images/ReleaseNotesIndicator.imageset/Document-Color-16.pdf diff --git a/DuckDuckGo/Assets.xcassets/Images/ReleaseNotesIndicator.imageset/Contents.json b/DuckDuckGo/Assets.xcassets/Images/ReleaseNotesIndicator.imageset/Contents.json new file mode 100644 index 00000000000..552be25080a --- /dev/null +++ b/DuckDuckGo/Assets.xcassets/Images/ReleaseNotesIndicator.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Document-Color-16.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/DuckDuckGo/Assets.xcassets/Images/ReleaseNotesIndicator.imageset/Document-Color-16.pdf b/DuckDuckGo/Assets.xcassets/Images/ReleaseNotesIndicator.imageset/Document-Color-16.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5db4a4627fe956be30544b99cfa3d54452b4a537 GIT binary patch literal 1327 zcmY!laBvK;I`dFTEr~!5FAK2q*+Jp}3?dH8Gc~f^ll-={ylbfjz&qzxA{f{=T?v zeZvvSA1#3b9Y26N6c{}?*KTBE-U<8~(|j zf45y&zAg3;%lpn3-TNLe3aDAgT|agG!Ow~!@7C4w=0-oSIZf?wRkGbyHqmHq%!U<* zMdzEQU+vvv^;IaFvsC$NxbI45i{GCdtq|H;TsWo|2P~sBnR%7 zFj6$MZ%I6M_V0> zVcVVS|5tHHD6c9|n$z?k`lM}y-uDB3jJKWkx~sIQ=M;udeyOS+d57&?tjG~%%x)1#*M3tL0YHBruE;!QF>#5?F_-Q|-O{cT*FJl) zW?#i2ftMGyX7MfXZeBmxGG_h+8NSMjy|$n2QWyGn?V8~*Nubl{nNU-=tD~ z1-=Ovj$WU&q;KIg4b7w{i~Uz#NfURSEl_^u<-T22(aon9`^@#q3=2u;>9)F;)jpTm z#VkjAYbmGyjIAzCdR+z2EfUfz5>_*GTNRi-;=Jv#TmNHA?(8=z-O>3Bjhk8DTv-(G zUQ{9S%Ir7WPAi48N%YMWk=c+to%36hFN0~8PagAkJuZa@oZp!i{MeCl;Ye4@PqtP4 z{tmAMjK%J^2MK7pt8g)2B$i8jzqK(`R$y}fy}5bT=Eb~u(`KLh zVa1#IJE8Y&!IU=1(qpMr2?_d6@hX?s2{$ycZws9&;`Pz(Tv+#Kr(fK+>L&aLC2nZy zge7xOx`iZvGgC`=;x~bd0yBlaV_sf_{hGsA!1Pf+TP-=00X;E@&u>vR?g7Ob2OF8G~m89kYZ3N{(m|#F+5l~FQ z6e@(2Q$a%T9IWr1nF4gG0>}qJ3NU+|^Gktx4Kdtb49T&uz%WBG3FN_IxP>5xK|Jo9 zSdy5NpN^`vq9`?u%Rs@L3*vncsbFSmYHX?i6ovvr0|hWkArCHO40I<5AcV}#%`t>5 zEzyN6&4FQqqS4U61n7LIP)Si@W=?7m7bx~TU4X%%QJkNfs;QunnW6~^6#bz5{1OF_ hhrt1?ADmg03UocV_)07)0ei>L(7=>SRn^ts4FDq#*%JT& literal 0 HcmV?d00001 diff --git a/DuckDuckGo/Tab/ViewModel/TabViewModel.swift b/DuckDuckGo/Tab/ViewModel/TabViewModel.swift index e9bae21191a..42c30675706 100644 --- a/DuckDuckGo/Tab/ViewModel/TabViewModel.swift +++ b/DuckDuckGo/Tab/ViewModel/TabViewModel.swift @@ -548,7 +548,7 @@ private extension NSAttributedString { title: UserText.duckPlayer) static let emailProtectionTrustedIndicator = trustedIndicatorAttributedString(with: .emailProtectionIcon, title: UserText.emailProtectionPreferences) - static let releaseNotesTrustedIndicator = trustedIndicatorAttributedString(with: .duckPlayerSettings, + static let releaseNotesTrustedIndicator = trustedIndicatorAttributedString(with: .releaseNotesIndicator, title: UserText.releaseNotesTitle) } diff --git a/DuckDuckGo/Updates/UpdateController.swift b/DuckDuckGo/Updates/UpdateController.swift index 428540ffc53..f0b7af5062a 100644 --- a/DuckDuckGo/Updates/UpdateController.swift +++ b/DuckDuckGo/Updates/UpdateController.swift @@ -232,14 +232,14 @@ extension UpdateController: SPUUpdaterDelegate { func updater(_ updater: SPUUpdater, didFindValidUpdate item: SUAppcastItem) { os_log("Updater did find valid update: \(item.displayVersionString)(\(item.versionString))", log: .updates) + PixelKit.fire(DebugEvent(GeneralPixel.updaterDidFindUpdate)) + guard !areAutomaticUpdatesEnabled else { // If automatic updates are enabled, we are waiting until the update is downloaded return } // For manual updates, show the available update without downloading onUpdateCheckEnd(item: item, isInstalled: false) - - PixelKit.fire(DebugEvent(GeneralPixel.updaterDidFindUpdate)) } func updaterDidNotFindUpdate(_ updater: SPUUpdater, error: any Error) { diff --git a/LocalPackages/SwiftUIExtensions/Sources/SwiftUIExtensions/Assets.xcassets/Images/UpdateNotificationClose.imageset/Contents.json b/LocalPackages/SwiftUIExtensions/Sources/SwiftUIExtensions/Assets.xcassets/Images/UpdateNotificationClose.imageset/Contents.json index dd995134167..febda811fdb 100644 --- a/LocalPackages/SwiftUIExtensions/Sources/SwiftUIExtensions/Assets.xcassets/Images/UpdateNotificationClose.imageset/Contents.json +++ b/LocalPackages/SwiftUIExtensions/Sources/SwiftUIExtensions/Assets.xcassets/Images/UpdateNotificationClose.imageset/Contents.json @@ -8,5 +8,8 @@ "info" : { "author" : "xcode", "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" } } From 0009c0edbf74374b14f88760e42bf169e4d58bcf Mon Sep 17 00:00:00 2001 From: Dax the Duck Date: Tue, 6 Aug 2024 14:15:01 +0000 Subject: [PATCH 19/32] Bump version to 1.100.1 (240) --- Configuration/BuildNumber.xcconfig | 2 +- Configuration/Version.xcconfig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index 773f6594824..a0e4c363e3e 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 238 +CURRENT_PROJECT_VERSION = 240 diff --git a/Configuration/Version.xcconfig b/Configuration/Version.xcconfig index f74ff7935d2..6ad0f4b7a03 100644 --- a/Configuration/Version.xcconfig +++ b/Configuration/Version.xcconfig @@ -1 +1 @@ -MARKETING_VERSION = 1.100.0 +MARKETING_VERSION = 1.100.1 From 2051b85db9be09d92aa6a18ed7b579bcf7141681 Mon Sep 17 00:00:00 2001 From: Sabrina Tardio <44158575+SabrinaTardio@users.noreply.github.com> Date: Tue, 6 Aug 2024 17:39:22 +0200 Subject: [PATCH 20/32] remove onboarding experiment (#3077) Task/Issue URL: https://app.asana.com/0/1204186595873227/1207981214658238/f **Description**: Turns Onboarding experiment off --- DuckDuckGo/Statistics/Experiment/PixelExperiment.swift | 4 ++-- DuckDuckGo/Tab/Model/Tab.swift | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/DuckDuckGo/Statistics/Experiment/PixelExperiment.swift b/DuckDuckGo/Statistics/Experiment/PixelExperiment.swift index 04465aa90fb..58fdee2b3ae 100644 --- a/DuckDuckGo/Statistics/Experiment/PixelExperiment.swift +++ b/DuckDuckGo/Statistics/Experiment/PixelExperiment.swift @@ -60,8 +60,8 @@ enum PixelExperiment: String, CaseIterable { // These are the variants. Rename or add/remove them as needed. If you change the string value // remember to keep it clear for privacy triage. - case control = "oa" - case newOnboarding = "ob" + case control +// case newOnboarding = "ob" } // These functions contain the business logic for determining if the pixel should be fired or not. diff --git a/DuckDuckGo/Tab/Model/Tab.swift b/DuckDuckGo/Tab/Model/Tab.swift index 99e65988834..7a1fd12d30b 100644 --- a/DuckDuckGo/Tab/Model/Tab.swift +++ b/DuckDuckGo/Tab/Model/Tab.swift @@ -727,11 +727,11 @@ protocol NewWindowPolicyDecisionMaker { } #endif - if PixelExperiment.cohort == .newOnboarding { - setContent(.onboarding) - } else { +// if PixelExperiment.cohort == .newOnboarding { +// setContent(.onboarding) +// } else { setContent(.onboardingDeprecated) - } +// } } @MainActor(unsafe) From f0727fc0874676511c7e11e4dfa4afca53f30608 Mon Sep 17 00:00:00 2001 From: Fernando Bunn Date: Tue, 6 Aug 2024 17:18:00 +0100 Subject: [PATCH 21/32] Handle contingency settings state on remote config (#3070) Task/Issue URL: https://app.asana.com/0/0/1207976963085129/f Tech Design URL: CC: **Description**: Display DuckPlayer contingency message and disable settings if necessary --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 4 ++-- DuckDuckGo/Preferences/Model/DuckPlayerPreferences.swift | 8 +++++--- .../Preferences/View/PreferencesDuckPlayerView.swift | 4 ++-- .../Preferences/View/PreferencesViewController.swift | 2 +- DuckDuckGo/YoutubePlayer/DuckPlayer.swift | 4 ++++ LocalPackages/DataBrokerProtection/Package.swift | 2 +- LocalPackages/NetworkProtectionMac/Package.swift | 2 +- LocalPackages/SubscriptionUI/Package.swift | 2 +- 9 files changed, 18 insertions(+), 12 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 8498cca34f6..f38c316f2f8 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -13432,7 +13432,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 180.0.1; + version = 181.0.0; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 50bef80e9be..24f3a1363dd 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "a3b3df069bbaa06149e43ca26e5df219ee61aa15", - "version" : "180.0.1" + "revision" : "1d5b3d0a52f75ec5899ae79aabe6c879102cf218", + "version" : "181.0.0" } }, { diff --git a/DuckDuckGo/Preferences/Model/DuckPlayerPreferences.swift b/DuckDuckGo/Preferences/Model/DuckPlayerPreferences.swift index 00be35f086f..06549b1d711 100644 --- a/DuckDuckGo/Preferences/Model/DuckPlayerPreferences.swift +++ b/DuckDuckGo/Preferences/Model/DuckPlayerPreferences.swift @@ -20,6 +20,7 @@ import Foundation import Combine import BrowserServicesKit import PixelKit +import DuckPlayer protocol DuckPlayerPreferencesPersistor { /// The persistor hadles raw Bool values but each one translates into a DuckPlayerMode: @@ -52,6 +53,7 @@ struct DuckPlayerPreferencesUserDefaultsPersistor: DuckPlayerPreferencesPersisto final class DuckPlayerPreferences: ObservableObject { private let internalUserDecider: InternalUserDecider + private let duckPlayerContingencyHandler: DuckPlayerContingencyHandler static let shared = DuckPlayerPreferences() private let privacyConfigurationManager: PrivacyConfigurationManaging @@ -112,13 +114,12 @@ final class DuckPlayerPreferences: ObservableObject { } var shouldDisplayContingencyMessage: Bool { - false + duckPlayerContingencyHandler.shouldDisplayContingencyMessage } @MainActor func openLearnMoreContingencyURL() { - #warning("DuckPlayer - Replace this with real URL") - guard let url = URL(string: "https://duckduckgo.com/duckduckgo-help-pages/duck-player/") else { return } + guard let url = duckPlayerContingencyHandler.learnMoreURL else { return } WindowControllersManager.shared.show(url: url, source: .ui, newTab: true) } @@ -133,6 +134,7 @@ final class DuckPlayerPreferences: ObservableObject { duckPlayerOpenInNewTab = persistor.duckPlayerOpenInNewTab self.privacyConfigurationManager = privacyConfigurationManager self.internalUserDecider = internalUserDecider + self.duckPlayerContingencyHandler = DefaultDuckPlayerContingencyHandler(privacyConfigurationManager: privacyConfigurationManager) } private var persistor: DuckPlayerPreferencesPersistor diff --git a/DuckDuckGo/Preferences/View/PreferencesDuckPlayerView.swift b/DuckDuckGo/Preferences/View/PreferencesDuckPlayerView.swift index 12e6209597e..c39282d4879 100644 --- a/DuckDuckGo/Preferences/View/PreferencesDuckPlayerView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesDuckPlayerView.swift @@ -76,7 +76,7 @@ extension Preferences { .offset(x: PreferencesViews.Const.pickerHorizontalOffset) TextMenuItemCaption(UserText.duckPlayerExplanation) - } + }.disabled(model.shouldDisplayContingencyMessage) if model.shouldDisplayAutoPlaySettings || model.isOpenInNewTabSettingsAvailable { PreferencePaneSection(UserText.duckPlayerVideoPreferencesTitle) { @@ -89,7 +89,7 @@ extension Preferences { ToggleMenuItem(UserText.duckPlayerNewTabPreference, isOn: $model.duckPlayerOpenInNewTab) .disabled(!model.isNewTabSettingsAvailable) } - } + }.disabled(model.shouldDisplayContingencyMessage) } } diff --git a/DuckDuckGo/Preferences/View/PreferencesViewController.swift b/DuckDuckGo/Preferences/View/PreferencesViewController.swift index 3f464516246..40055bab2f7 100644 --- a/DuckDuckGo/Preferences/View/PreferencesViewController.swift +++ b/DuckDuckGo/Preferences/View/PreferencesViewController.swift @@ -36,7 +36,7 @@ final class PreferencesViewController: NSViewController { init(syncService: DDGSyncing, duckPlayer: DuckPlayer = DuckPlayer.shared) { model = PreferencesSidebarModel(syncService: syncService, vpnGatekeeper: DefaultVPNFeatureGatekeeper(subscriptionManager: Application.appDelegate.subscriptionManager), - includeDuckPlayer: duckPlayer.isAvailable) + includeDuckPlayer: duckPlayer.shouldDisplayPreferencesSideBar) super.init(nibName: nil, bundle: nil) } diff --git a/DuckDuckGo/YoutubePlayer/DuckPlayer.swift b/DuckDuckGo/YoutubePlayer/DuckPlayer.swift index 4fb257e3abc..d1cd1602f3c 100644 --- a/DuckDuckGo/YoutubePlayer/DuckPlayer.swift +++ b/DuckDuckGo/YoutubePlayer/DuckPlayer.swift @@ -139,6 +139,10 @@ final class DuckPlayer { preferences.youtubeOverlayInteracted } + var shouldDisplayPreferencesSideBar: Bool { + isAvailable || preferences.shouldDisplayContingencyMessage + } + init( preferences: DuckPlayerPreferences = .shared, privacyConfigurationManager: PrivacyConfigurationManaging = ContentBlocking.shared.privacyConfigurationManager diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index abefa9639e6..662af68bc7c 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "181.0.0"), .package(path: "../SwiftUIExtensions"), .package(path: "../XPCHelper"), ], diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index 9bea4fce247..4914ce0d21d 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -32,7 +32,7 @@ let package = Package( .library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "181.0.0"), .package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"), .package(path: "../AppLauncher"), .package(path: "../UDSHelper"), diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index b75fff50610..87962fee651 100644 --- a/LocalPackages/SubscriptionUI/Package.swift +++ b/LocalPackages/SubscriptionUI/Package.swift @@ -12,7 +12,7 @@ let package = Package( targets: ["SubscriptionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "181.0.0"), .package(path: "../SwiftUIExtensions") ], targets: [ From a93a9337b5be206fb50afd764691c97593cad6ae Mon Sep 17 00:00:00 2001 From: Dax the Duck Date: Tue, 6 Aug 2024 16:54:02 +0000 Subject: [PATCH 22/32] Bump version to 1.101.0 (241) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index a0e4c363e3e..2cfc7bd898a 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 240 +CURRENT_PROJECT_VERSION = 241 From 638783390b3454d90530d79273435299959a9f8f Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Tue, 6 Aug 2024 18:58:12 +0200 Subject: [PATCH 23/32] Disables a flaky test --- .../xcshareddata/xcschemes/DuckDuckGo Privacy Browser.xcscheme | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser.xcscheme b/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser.xcscheme index 6b556706634..0b89d131eb3 100644 --- a/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser.xcscheme +++ b/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser.xcscheme @@ -189,6 +189,9 @@ + + Date: Wed, 7 Aug 2024 11:50:05 +0200 Subject: [PATCH 24/32] Pushes a tentative fix for the media permissions crash (#3075) Task/Issue URL: https://app.asana.com/0/1203108348835387/1207988315342624/f ## Description Tentative fix for media permissions crash. --- DuckDuckGo/Permissions/Model/PermissionModel.swift | 2 +- DuckDuckGo/Tab/Model/Tab+UIDelegate.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DuckDuckGo/Permissions/Model/PermissionModel.swift b/DuckDuckGo/Permissions/Model/PermissionModel.swift index 35bf07fe4f9..0bd5dc95e3a 100644 --- a/DuckDuckGo/Permissions/Model/PermissionModel.swift +++ b/DuckDuckGo/Permissions/Model/PermissionModel.swift @@ -226,7 +226,7 @@ final class PermissionModel { // MARK: - WebView delegated methods // Called before requestMediaCapturePermissionFor: to validate System Permissions - func checkUserMediaPermission(for url: URL, mainFrameURL: URL, decisionHandler: @escaping (String, Bool) -> Void) { + func checkUserMediaPermission(for url: URL?, mainFrameURL: URL?, decisionHandler: @escaping (String, Bool) -> Void) { // If media capture is denied in the System Preferences, reflect it in the current permissions // AVCaptureDevice.authorizationStatus(for:mediaType) is swizzled to determine requested media type // otherwise WebView won't call any other delegate methods if System Permission is denied diff --git a/DuckDuckGo/Tab/Model/Tab+UIDelegate.swift b/DuckDuckGo/Tab/Model/Tab+UIDelegate.swift index 81b12ca0b04..69b769e0658 100644 --- a/DuckDuckGo/Tab/Model/Tab+UIDelegate.swift +++ b/DuckDuckGo/Tab/Model/Tab+UIDelegate.swift @@ -176,11 +176,11 @@ extension Tab: WKUIDelegate, PrintingUserScriptDelegate { @objc(_webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:) func webView(_ webView: WKWebView, - checkUserMediaPermissionFor url: URL, - mainFrameURL: URL, + checkUserMediaPermissionFor url: NSURL?, + mainFrameURL: NSURL?, frameIdentifier: UInt64, decisionHandler: @escaping (String, Bool) -> Void) { - self.permissions.checkUserMediaPermission(for: url, mainFrameURL: mainFrameURL, decisionHandler: decisionHandler) + self.permissions.checkUserMediaPermission(for: url as? URL, mainFrameURL: mainFrameURL as? URL, decisionHandler: decisionHandler) } // https://github.com/WebKit/WebKit/blob/995f6b1595611c934e742a4f3a9af2e678bc6b8d/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h#L147 From 1766b1d41782dbfae040facf260f3bec6cd981a2 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 7 Aug 2024 13:42:02 +0200 Subject: [PATCH 25/32] Stop VPN is no longer guarded by the VPN feature gatekeeper (#3079) Task/Issue URL: https://app.asana.com/0/1207603085593419/1207992369875462/f ## Description Changes the code so that stopping the tunnel can't be prevented by `VPNFeatureGatekeeper`. --- .../NetworkProtectionIPCTunnelController.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DuckDuckGo/NetworkProtection/AppTargets/DeveloperIDTarget/NetworkProtectionIPCTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/DeveloperIDTarget/NetworkProtectionIPCTunnelController.swift index 029b3dc4c0e..960974ff290 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/DeveloperIDTarget/NetworkProtectionIPCTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/DeveloperIDTarget/NetworkProtectionIPCTunnelController.swift @@ -74,10 +74,6 @@ final class NetworkProtectionIPCTunnelController { // MARK: - Login Items Manager private func enableLoginItems() async throws { - guard try await featureGatekeeper.canStartVPN() else { - throw RequestError.notAuthorizedToEnableLoginItem - } - do { try loginItemsManager.throwingEnableLoginItems(LoginItemsManager.networkProtectionLoginItems, log: .networkProtection) } catch { @@ -103,6 +99,10 @@ extension NetworkProtectionIPCTunnelController: TunnelController { } do { + guard try await featureGatekeeper.canStartVPN() else { + throw RequestError.notAuthorizedToEnableLoginItem + } + try await enableLoginItems() knownFailureStore.reset() From 47731ad3aa3892ca1fa94ad38bf48a5843ea604d Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 7 Aug 2024 15:59:58 +0200 Subject: [PATCH 26/32] Push domain exclusions to internal release (#3076) Task/Issue URL: https://app.asana.com/0/0/1207987809385256/f BSK PR: https://github.com/duckduckgo/BrowserServicesKit/pull/928 iOS PR: https://github.com/duckduckgo/iOS/pull/3195 ## Description Implements domain exclusions for internal users only. --- DuckDuckGo.xcodeproj/project.pbxproj | 70 ++++++- .../xcshareddata/swiftpm/Package.resolved | 4 +- ...kDuckGo Privacy Browser App Store.xcscheme | 6 + .../DuckDuckGo Privacy Browser.xcscheme | 6 + DuckDuckGo/Application/URLEventHandler.swift | 39 +--- .../UserText+NetworkProtection.swift | 12 ++ .../View/NavigationBarPopovers.swift | 20 +- .../ActiveDomainPublisher.swift | 100 ++++++++++ .../NetworkProtectionDebugMenu.swift | 24 ++- .../NetworkProtectionDebugUtilities.swift | 4 + ...etworkProtectionNavBarPopoverManager.swift | 66 +++++-- .../NetworkProtectionTunnelController.swift | 7 - .../SiteTroubleshootingInfoPublisher.swift | 111 +++++++++++ .../BothAppTargets/VPNUIActionHandler.swift | 65 ++++++ .../BothAppTargets/VPNURLEventHandler.swift | 91 +++++++++ .../AddExcludedDomainButtonsView.swift | 187 ++++++++++++++++++ .../AddExcludedDomainView.swift | 112 +++++++++++ .../ExcludedDomains.storyboard | 187 ++++++++++++++++++ .../ExcludedDomainsModel.swift | 54 +++++ .../ExcludedDomainsViewController.swift | 178 +++++++++++++++++ .../Model/VPNPreferencesModel.swift | 47 ++++- .../Preferences/View/PreferencesVPNView.swift | 19 +- .../Tab/View/BrowserTabViewController.swift | 2 +- .../View/WindowControllersManager.swift | 8 +- DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift | 7 +- .../TunnelControllerIPCService.swift | 3 + DuckDuckGoVPN/VPNUIActionHandler.swift | 58 ++++++ .../DataBrokerProtection/Package.swift | 2 +- .../NetworkProtectionMac/Package.swift | 2 +- .../FlowManagers/TCPFlowManager.swift | 22 ++- .../TransparentProxyAppMessageHandler.swift | 12 +- .../Settings/TransparentProxySettings.swift | 38 +++- .../TransparentProxyProvider.swift | 159 +++++++++------ .../Animation/AnimationConstants.swift | 23 +++ .../Menu/StatusBarMenu.swift | 45 +++-- .../NetworkProtectionAsset.swift | 3 + .../NetworkProtectionPopover.swift | 49 ++--- .../Icons/Check-16D.imageset/Check-16D.pdf | Bin 0 -> 1525 bytes .../Icons/Check-16D.imageset/Contents.json | 15 ++ .../SwiftUI/AccordionView.swift | 119 +++++++++++ .../SwiftUI/MenuItemButton.swift | 2 +- .../SwiftUI/MenuItemCustomButton.swift | 2 +- .../VPNUIActionHandling.swift} | 5 +- .../DebugInformationView.swift | 24 +-- .../DebugInformationViewModel.swift | 12 +- .../SiteTroubleshootingInfo.swift} | 28 ++- .../SiteTroubleshootingView.swift | 97 +++++++++ .../SiteTroubleshootingViewModel.swift | 88 +++++++++ .../NetworkProtectionStatusView.swift | 14 +- .../NetworkProtectionStatusViewModel.swift | 25 +-- .../TunnelControllerView.swift | 10 + .../TunnelControllerViewModel.swift | 12 +- .../MockVPNUIActionHandler.swift | 5 +- .../NetworkProtectionAssetTests.swift | 3 +- LocalPackages/SubscriptionUI/Package.swift | 2 +- .../View/NavigationBarPopoversTests.swift | 1 + 56 files changed, 2043 insertions(+), 263 deletions(-) create mode 100644 DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/ActiveDomainPublisher.swift create mode 100644 DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/SiteTroubleshootingInfoPublisher.swift create mode 100644 DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNUIActionHandler.swift create mode 100644 DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNURLEventHandler.swift create mode 100644 DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainButtonsView.swift create mode 100644 DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainView.swift create mode 100644 DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomains.storyboard create mode 100644 DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsModel.swift create mode 100644 DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsViewController.swift create mode 100644 DuckDuckGoVPN/VPNUIActionHandler.swift create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Animation/AnimationConstants.swift create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Check-16D.pdf create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Contents.json create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/AccordionView.swift rename LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/{VPNUIActionHandler/VPNUIActionHandler.swift => VPNUIActionHandling/VPNUIActionHandling.swift} (84%) rename LocalPackages/NetworkProtectionMac/Sources/{VPNAppLauncher/AppLauncher+VPNUIActionHandler.swift => NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingInfo.swift} (50%) create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingView.swift create mode 100644 LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingViewModel.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 4c86d42ff33..8d55d775a61 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -1576,11 +1576,27 @@ 7B4D8A222BDA857300852966 /* VPNOperationErrorRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4D8A202BDA857300852966 /* VPNOperationErrorRecorder.swift */; }; 7B4D8A232BDA857300852966 /* VPNOperationErrorRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4D8A202BDA857300852966 /* VPNOperationErrorRecorder.swift */; }; 7B4D8A242BDA857300852966 /* VPNOperationErrorRecorder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B4D8A202BDA857300852966 /* VPNOperationErrorRecorder.swift */; }; + 7B5A23682C468233007213AC /* ExcludedDomainsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5A23672C468233007213AC /* ExcludedDomainsViewController.swift */; }; + 7B5A23692C468233007213AC /* ExcludedDomainsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5A23672C468233007213AC /* ExcludedDomainsViewController.swift */; }; + 7B5A236F2C46A116007213AC /* ExcludedDomainsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5A236E2C46A116007213AC /* ExcludedDomainsModel.swift */; }; + 7B5A23702C46A116007213AC /* ExcludedDomainsModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B5A236E2C46A116007213AC /* ExcludedDomainsModel.swift */; }; + 7B5A23752C46A4A8007213AC /* ExcludedDomains.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7B5A23742C46A4A8007213AC /* ExcludedDomains.storyboard */; }; + 7B5A23762C46A4A8007213AC /* ExcludedDomains.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7B5A23742C46A4A8007213AC /* ExcludedDomains.storyboard */; }; + 7B60AFFA2C511B65008E32A3 /* VPNUIActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60AFF92C511B65008E32A3 /* VPNUIActionHandler.swift */; }; + 7B60AFFB2C511C68008E32A3 /* VPNUIActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60AFF92C511B65008E32A3 /* VPNUIActionHandler.swift */; }; + 7B60AFFE2C514269008E32A3 /* VPNURLEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60AFFC2C514260008E32A3 /* VPNURLEventHandler.swift */; }; + 7B60AFFF2C51426A008E32A3 /* VPNURLEventHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60AFFC2C514260008E32A3 /* VPNURLEventHandler.swift */; }; + 7B60B0022C5145EC008E32A3 /* VPNUIActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60B0002C514541008E32A3 /* VPNUIActionHandler.swift */; }; + 7B60B0032C5145ED008E32A3 /* VPNUIActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B60B0002C514541008E32A3 /* VPNUIActionHandler.swift */; }; 7B624F172BA25C1F00A6C544 /* NetworkProtectionUI in Frameworks */ = {isa = PBXBuildFile; productRef = 7B624F162BA25C1F00A6C544 /* NetworkProtectionUI */; }; 7B6545ED2C0778BB00115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6545EC2C0778BB00115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift */; }; 7B6545EE2C0779D500115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B6545EC2C0778BB00115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift */; }; 7B7DFB202B7E736B009EA1A3 /* MacPacketTunnelProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEF12E6D2A2111880023E6BF /* MacPacketTunnelProvider.swift */; }; 7B7DFB222B7E7473009EA1A3 /* Networking in Frameworks */ = {isa = PBXBuildFile; productRef = 7B7DFB212B7E7473009EA1A3 /* Networking */; }; + 7B7F5D212C526CE600826256 /* AddExcludedDomainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7F5D202C526CE600826256 /* AddExcludedDomainView.swift */; }; + 7B7F5D222C526CE600826256 /* AddExcludedDomainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7F5D202C526CE600826256 /* AddExcludedDomainView.swift */; }; + 7B7F5D242C52725A00826256 /* AddExcludedDomainButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7F5D232C52725A00826256 /* AddExcludedDomainButtonsView.swift */; }; + 7B7F5D252C52725A00826256 /* AddExcludedDomainButtonsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7F5D232C52725A00826256 /* AddExcludedDomainButtonsView.swift */; }; 7B7FCD0F2BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7FCD0E2BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift */; }; 7B7FCD102BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7FCD0E2BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift */; }; 7B8594192B5B26230007EB3E /* UDSHelper in Frameworks */ = {isa = PBXBuildFile; productRef = 7B8594182B5B26230007EB3E /* UDSHelper */; }; @@ -1622,6 +1638,10 @@ 7BAF9E4C2A8A3CCA002D3B6E /* UserDefaults+NetworkProtectionShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B934C402A866DD400FC8F9C /* UserDefaults+NetworkProtectionShared.swift */; }; 7BAF9E4D2A8A3CCB002D3B6E /* UserDefaults+NetworkProtectionShared.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B934C402A866DD400FC8F9C /* UserDefaults+NetworkProtectionShared.swift */; }; 7BB108592A43375D000AB95F /* PFMoveApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 7BB108582A43375D000AB95F /* PFMoveApplication.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 7BB4BC632C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB4BC622C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift */; }; + 7BB4BC642C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB4BC622C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift */; }; + 7BB4BC6A2C5CD96200E06FC8 /* ActiveDomainPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB4BC692C5CD96200E06FC8 /* ActiveDomainPublisher.swift */; }; + 7BB4BC6B2C5CD96200E06FC8 /* ActiveDomainPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BB4BC692C5CD96200E06FC8 /* ActiveDomainPublisher.swift */; }; 7BBD45B12A691AB500C83CA9 /* NetworkProtectionDebugUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBD45B02A691AB500C83CA9 /* NetworkProtectionDebugUtilities.swift */; }; 7BBD45B22A691AB500C83CA9 /* NetworkProtectionDebugUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BBD45B02A691AB500C83CA9 /* NetworkProtectionDebugUtilities.swift */; }; 7BBE2B7B2B61663C00697445 /* NetworkProtectionProxy in Frameworks */ = {isa = PBXBuildFile; productRef = 7BBE2B7A2B61663C00697445 /* NetworkProtectionProxy */; }; @@ -3512,10 +3532,18 @@ 7B4D8A202BDA857300852966 /* VPNOperationErrorRecorder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNOperationErrorRecorder.swift; sourceTree = ""; }; 7B5291882A1697680022E406 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 7B5291892A169BC90022E406 /* DeveloperID.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DeveloperID.xcconfig; sourceTree = ""; }; + 7B5A23672C468233007213AC /* ExcludedDomainsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExcludedDomainsViewController.swift; sourceTree = ""; }; + 7B5A236E2C46A116007213AC /* ExcludedDomainsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExcludedDomainsModel.swift; sourceTree = ""; }; + 7B5A23742C46A4A8007213AC /* ExcludedDomains.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = ExcludedDomains.storyboard; sourceTree = ""; }; + 7B60AFF92C511B65008E32A3 /* VPNUIActionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNUIActionHandler.swift; sourceTree = ""; }; + 7B60AFFC2C514260008E32A3 /* VPNURLEventHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNURLEventHandler.swift; sourceTree = ""; }; + 7B60B0002C514541008E32A3 /* VPNUIActionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNUIActionHandler.swift; sourceTree = ""; }; 7B6545EC2C0778BB00115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VPNControllerUDSClient+ConvenienceInitializers.swift"; sourceTree = ""; }; 7B6EC5E42AE2D8AF004FE6DF /* DuckDuckGoDBPAgentAppStore.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DuckDuckGoDBPAgentAppStore.xcconfig; sourceTree = ""; }; 7B6EC5E52AE2D8AF004FE6DF /* DuckDuckGoDBPAgent.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = DuckDuckGoDBPAgent.xcconfig; sourceTree = ""; }; 7B76E6852AD5D77600186A84 /* XPCHelper */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = XPCHelper; sourceTree = ""; }; + 7B7F5D202C526CE600826256 /* AddExcludedDomainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddExcludedDomainView.swift; sourceTree = ""; }; + 7B7F5D232C52725A00826256 /* AddExcludedDomainButtonsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddExcludedDomainButtonsView.swift; sourceTree = ""; }; 7B7FCD0E2BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserDefaults+vpnLegacyUser.swift"; sourceTree = ""; }; 7B8594172B5B25FB0007EB3E /* UDSHelper */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = UDSHelper; sourceTree = ""; }; 7B8DB3192B504D7500EC16DA /* VPNAppEventsHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VPNAppEventsHandler.swift; sourceTree = ""; }; @@ -3537,6 +3565,8 @@ 7BA7CC4D2AD11F6F0042E5CE /* NetworkProtectionIPCTunnelController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkProtectionIPCTunnelController.swift; sourceTree = ""; }; 7BB108572A43375D000AB95F /* PFMoveApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PFMoveApplication.h; sourceTree = ""; }; 7BB108582A43375D000AB95F /* PFMoveApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PFMoveApplication.m; sourceTree = ""; }; + 7BB4BC622C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteTroubleshootingInfoPublisher.swift; sourceTree = ""; }; + 7BB4BC692C5CD96200E06FC8 /* ActiveDomainPublisher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActiveDomainPublisher.swift; sourceTree = ""; }; 7BBD45B02A691AB500C83CA9 /* NetworkProtectionDebugUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkProtectionDebugUtilities.swift; sourceTree = ""; }; 7BCB90C12C18626E008E3543 /* VPNControllerXPCClient+ConvenienceInitializers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "VPNControllerXPCClient+ConvenienceInitializers.swift"; sourceTree = ""; }; 7BD1688D2AD4A4C400D24876 /* NetworkExtensionController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NetworkExtensionController.swift; sourceTree = ""; }; @@ -5324,6 +5354,7 @@ 4B4D60572A0B29FA00BCD287 /* AppAndExtensionTargets */, 4B4D60602A0B29FA00BCD287 /* AppTargets */, 4B4D60742A0B29FA00BCD287 /* NetworkExtensionTargets */, + 7B5A236D2C46A0DA007213AC /* ExcludedDomains */, ); path = NetworkProtection; sourceTree = ""; @@ -5367,6 +5398,8 @@ 4B4D60632A0B29FA00BCD287 /* BothAppTargets */ = { isa = PBXGroup; children = ( + 7BB4BC692C5CD96200E06FC8 /* ActiveDomainPublisher.swift */, + 7BB4BC622C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift */, 4B4D60722A0B29FA00BCD287 /* EventMapping+NetworkProtectionError.swift */, BDE981DB2BBD110800645880 /* Assets */, 7BD3AF5C2A8E7AF1006F9F56 /* KeychainType+ClientDefault.swift */, @@ -5388,6 +5421,8 @@ 7B934C3D2A866CFF00FC8F9C /* NetworkProtectionOnboardingMenu.swift */, B6F1B02D2BCE6B47005E863C /* TunnelControllerProvider.swift */, 4BE3A6C02C16BEB1003FC378 /* VPNRedditSessionWorkaround.swift */, + 7B60B0002C514541008E32A3 /* VPNUIActionHandler.swift */, + 7B60AFFC2C514260008E32A3 /* VPNURLEventHandler.swift */, ); path = BothAppTargets; sourceTree = ""; @@ -6108,6 +6143,18 @@ path = UITests; sourceTree = ""; }; + 7B5A236D2C46A0DA007213AC /* ExcludedDomains */ = { + isa = PBXGroup; + children = ( + 7B5A23742C46A4A8007213AC /* ExcludedDomains.storyboard */, + 7B5A23672C468233007213AC /* ExcludedDomainsViewController.swift */, + 7B5A236E2C46A116007213AC /* ExcludedDomainsModel.swift */, + 7B7F5D202C526CE600826256 /* AddExcludedDomainView.swift */, + 7B7F5D232C52725A00826256 /* AddExcludedDomainButtonsView.swift */, + ); + path = ExcludedDomains; + sourceTree = ""; + }; 7B6EC5E32AE2D88C004FE6DF /* DBP */ = { isa = PBXGroup; children = ( @@ -6129,6 +6176,7 @@ isa = PBXGroup; children = ( 7BA7CC132AD11DC80042E5CE /* AppLauncher+DefaultInitializer.swift */, + 7B60AFF92C511B65008E32A3 /* VPNUIActionHandler.swift */, 7BA7CC0E2AD11DC80042E5CE /* DuckDuckGoVPNAppDelegate.swift */, 7BD1688D2AD4A4C400D24876 /* NetworkExtensionController.swift */, EEDE50102BA360C80017F3C4 /* NetworkProtection+VPNAgentConvenienceInitializers.swift */, @@ -9240,6 +9288,7 @@ 3706FCD0293F65D500E42796 /* BookmarksBarCollectionViewItem.xib in Resources */, 3706FCD2293F65D500E42796 /* shield.json in Resources */, 3706FCD4293F65D500E42796 /* TabBarViewItem.xib in Resources */, + 7B5A23762C46A4A8007213AC /* ExcludedDomains.storyboard in Resources */, 3706FCD6293F65D500E42796 /* httpsMobileV2FalsePositives.json in Resources */, 3706FCD8293F65D500E42796 /* BookmarksBar.storyboard in Resources */, 3706FCD9293F65D500E42796 /* trackers-1.json in Resources */, @@ -9432,6 +9481,7 @@ 4BE5336B286912D40019DBFD /* BookmarksBarCollectionViewItem.xib in Resources */, AA34396C2754D4E300B241FA /* shield.json in Resources */, AA7412B324D0B3AC00D22FE0 /* TabBarViewItem.xib in Resources */, + 7B5A23752C46A4A8007213AC /* ExcludedDomains.storyboard in Resources */, 4B677435255DBEB800025BD8 /* httpsMobileV2FalsePositives.json in Resources */, 4BD18F05283F151F00058124 /* BookmarksBar.storyboard in Resources */, AA3439792754D55100B241FA /* trackers-1.json in Resources */, @@ -9875,6 +9925,7 @@ 3706FAAD293F65D500E42796 /* BadgeNotificationAnimationModel.swift in Sources */, 3706FAAE293F65D500E42796 /* HyperLink.swift in Sources */, 3706FAAF293F65D500E42796 /* PasteboardWriting.swift in Sources */, + 7B5A23692C468233007213AC /* ExcludedDomainsViewController.swift in Sources */, B6E3E5512BBFCDEE00A41922 /* OpenDownloadsCellView.swift in Sources */, 3706FAB0293F65D500E42796 /* BookmarkOutlineCellView.swift in Sources */, 3706FAB1293F65D500E42796 /* UnprotectedDomains.xcdatamodeld in Sources */, @@ -10208,6 +10259,7 @@ 3706FB93293F65D500E42796 /* PasteboardFolder.swift in Sources */, 3706FB94293F65D500E42796 /* CookieManagedNotificationView.swift in Sources */, EEC4A65F2B277EE100F7C0AA /* VPNLocationViewModel.swift in Sources */, + 7B60B0032C5145ED008E32A3 /* VPNUIActionHandler.swift in Sources */, 370A34B22AB24E3700C77F7C /* SyncDebugMenu.swift in Sources */, 4B4D60BE2A0C848A00BCD287 /* NetworkProtection+ConvenienceInitializers.swift in Sources */, 3706FB95293F65D500E42796 /* PermissionType.swift in Sources */, @@ -10270,6 +10322,7 @@ 3706FBBC293F65D500E42796 /* NSViewExtension.swift in Sources */, 3706FBBE293F65D500E42796 /* DownloadListViewModel.swift in Sources */, 3706FBBF293F65D500E42796 /* BookmarkManagementDetailViewController.swift in Sources */, + 7BB4BC642C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift in Sources */, B6B4D1CB2B0C8C9200C26286 /* FirefoxCompatibilityPreferences.swift in Sources */, F188268E2BBF01C400D9AC4F /* PixelDataModel.xcdatamodeld in Sources */, 3706FBC0293F65D500E42796 /* CSVImporter.swift in Sources */, @@ -10355,6 +10408,7 @@ 9F56CFAE2B84326C00BB7F11 /* AddEditBookmarkDialogViewModel.swift in Sources */, 3706FBF3293F65D500E42796 /* PseudoFolder.swift in Sources */, 1D26EBAD2B74BECB0002A93F /* NSImageSendable.swift in Sources */, + 7B7F5D252C52725A00826256 /* AddExcludedDomainButtonsView.swift in Sources */, 1D220BFD2B87AACF00F8BBC6 /* PrivacyProtectionStatus.swift in Sources */, 3706FBF8293F65D500E42796 /* TabBarFooter.swift in Sources */, B626A7612992407D00053070 /* CancellableExtension.swift in Sources */, @@ -10505,6 +10559,7 @@ 3706FC53293F65D500E42796 /* TabBarScrollView.swift in Sources */, B6104E9C2BA9C173008636B2 /* DownloadResumeData.swift in Sources */, 3706FC54293F65D500E42796 /* BookmarkListTreeControllerDataSource.swift in Sources */, + 7B7F5D222C526CE600826256 /* AddExcludedDomainView.swift in Sources */, 3706FC55293F65D500E42796 /* AddressBarViewController.swift in Sources */, 3706FC56293F65D500E42796 /* Permissions.swift in Sources */, 9F872D992B8DA9F800138637 /* Bookmarks+Tab.swift in Sources */, @@ -10537,6 +10592,7 @@ 7B6545EE2C0779D500115BEA /* VPNControllerUDSClient+ConvenienceInitializers.swift in Sources */, B6F9BDE52B45CD1900677B33 /* ModalView.swift in Sources */, 9F872DA42B90920F00138637 /* BookmarkFolderInfo.swift in Sources */, + 7B60AFFE2C514269008E32A3 /* VPNURLEventHandler.swift in Sources */, B677FC502B06376B0099EB04 /* ReportFeedbackView.swift in Sources */, 3706FC68293F65D500E42796 /* ToggleableScrollView.swift in Sources */, 3706FC69293F65D500E42796 /* UserScripts.swift in Sources */, @@ -10574,6 +10630,7 @@ 4BCBE4552BA7E16600FC75A1 /* NetworkProtectionSubscriptionEventHandler.swift in Sources */, 371209312C233D69003ADF3D /* RemoteMessagingStoreErrorHandling.swift in Sources */, 3706FC83293F65D500E42796 /* PopoverMessageViewController.swift in Sources */, + 7B5A23702C46A116007213AC /* ExcludedDomainsModel.swift in Sources */, 4BF97ADA2B43C5DC00EB4240 /* VPNFeedbackCategory.swift in Sources */, 9D9AE86E2AA76D1F0026E7DC /* LoginItem+NetworkProtection.swift in Sources */, 3707C721294B5D2900682A9F /* WKMenuItemIdentifier.swift in Sources */, @@ -10608,6 +10665,7 @@ 3706FC9C293F65D500E42796 /* BookmarkStore.swift in Sources */, 3706FC9D293F65D500E42796 /* PrivacyDashboardViewController.swift in Sources */, B6A22B632B1E29D000ECD2BA /* DataImportSummaryViewModel.swift in Sources */, + 7BB4BC6B2C5CD96200E06FC8 /* ActiveDomainPublisher.swift in Sources */, 3706FC9E293F65D500E42796 /* PreferencesAppearanceView.swift in Sources */, 3706FC9F293F65D500E42796 /* NSMenuItemExtension.swift in Sources */, 3706FCA0293F65D500E42796 /* ContiguousBytesExtension.swift in Sources */, @@ -11076,6 +11134,7 @@ 7BA7CC402AD11E3D0042E5CE /* AppLauncher+DefaultInitializer.swift in Sources */, 7B0694982B6E980F00FA4DBA /* VPNProxyLauncher.swift in Sources */, BDA764842BC49E3F00D0400C /* NetworkProtectionVPNCountryLabelsModel.swift in Sources */, + 7B60AFFA2C511B65008E32A3 /* VPNUIActionHandler.swift in Sources */, B65DA5EF2A77CC3A00CBEE8D /* Bundle+NetworkProtectionExtensions.swift in Sources */, BDA7647F2BC4998900D0400C /* DefaultVPNLocationFormatter.swift in Sources */, 4BF0E5072AD2551A00FFEC9E /* NetworkProtectionPixelEvent.swift in Sources */, @@ -11115,6 +11174,7 @@ B65DA5F02A77CC3C00CBEE8D /* Bundle+NetworkProtectionExtensions.swift in Sources */, BDA764852BC49E4000D0400C /* NetworkProtectionVPNCountryLabelsModel.swift in Sources */, 7BAF9E4D2A8A3CCB002D3B6E /* UserDefaults+NetworkProtectionShared.swift in Sources */, + 7B60AFFB2C511C68008E32A3 /* VPNUIActionHandler.swift in Sources */, 7BA7CC392AD11E2D0042E5CE /* DuckDuckGoVPNAppDelegate.swift in Sources */, BDA764802BC4998A00D0400C /* DefaultVPNLocationFormatter.swift in Sources */, 7BA7CC552AD11FFB0042E5CE /* NetworkProtectionOptionKeyExtension.swift in Sources */, @@ -11388,6 +11448,7 @@ F18826912BC0105800D9AC4F /* PixelDataStore.swift in Sources */, B69B503E2726A12500758A2B /* AtbParser.swift in Sources */, 37F19A6528E1B3FB00740DC6 /* PreferencesDuckPlayerView.swift in Sources */, + 7B7F5D212C526CE600826256 /* AddExcludedDomainView.swift in Sources */, 4B92929E26670D2A00AD2C21 /* BookmarkSidebarTreeController.swift in Sources */, EEC4A6712B2C90AB00F7C0AA /* VPNLocationPreferenceItem.swift in Sources */, 85589E8727BBB8F20038AD11 /* HomePageFavoritesModel.swift in Sources */, @@ -11434,6 +11495,7 @@ 85774AFF2A713D3B00DE0561 /* BookmarksBarMenuFactory.swift in Sources */, 4B9292A026670D2A00AD2C21 /* SpacerNode.swift in Sources */, 3775913629AB9A1C00E26367 /* SyncManagementDialogViewController.swift in Sources */, + 7B7F5D242C52725A00826256 /* AddExcludedDomainButtonsView.swift in Sources */, B6C0BB6729AEFF8100AE8E3C /* BookmarkExtension.swift in Sources */, 4BE6547F271FCD4D008D1D63 /* PasswordManagementCreditCardModel.swift in Sources */, 31B4AF532901A4F20013585E /* NSEventExtension.swift in Sources */, @@ -11455,12 +11517,14 @@ 1D0DE93E2C3BA9840037ABC2 /* AppRestarter.swift in Sources */, 7BCB90C22C18626E008E3543 /* VPNControllerXPCClient+ConvenienceInitializers.swift in Sources */, 4B9DB0202A983B24000927DB /* ProductWaitlistRequest.swift in Sources */, + 7B60B0022C5145EC008E32A3 /* VPNUIActionHandler.swift in Sources */, 98779A0029999B64005D8EB6 /* Bookmark.xcdatamodeld in Sources */, 85589E9E27BFE4500038AD11 /* DefaultBrowserPromptView.swift in Sources */, 4B4032842AAAC24400CCA602 /* WaitlistActivationDateStore.swift in Sources */, 1D220BFC2B87AACF00F8BBC6 /* PrivacyProtectionStatus.swift in Sources */, AA512D1424D99D9800230283 /* FaviconManager.swift in Sources */, 7BB108592A43375D000AB95F /* PFMoveApplication.m in Sources */, + 7BB4BC632C5BC13D00E06FC8 /* SiteTroubleshootingInfoPublisher.swift in Sources */, 4B0AACAC28BC63ED001038AC /* ChromiumFaviconsReader.swift in Sources */, AABEE6AB24ACA0F90043105B /* SuggestionTableRowView.swift in Sources */, 37CD54CB27F2FDD100F1F7B9 /* DownloadsPreferences.swift in Sources */, @@ -11826,6 +11890,7 @@ C168B9AC2B31DC7E001AFAD9 /* AutofillNeverPromptWebsitesManager.swift in Sources */, 9FA173E72B7B122E00EE4E6E /* BookmarkDialogStackedContentView.swift in Sources */, F1C70D7C2BFF510000599292 /* SubscriptionEnvironment+Default.swift in Sources */, + 7B60AFFF2C51426A008E32A3 /* VPNURLEventHandler.swift in Sources */, D64A5FF82AEA5C2B00B6D6E7 /* HomeButtonMenuFactory.swift in Sources */, 37A6A8F62AFCCA59008580A3 /* FaviconsFetcherOnboardingViewController.swift in Sources */, AA3F895324C18AD500628DDE /* SuggestionViewModel.swift in Sources */, @@ -11833,6 +11898,7 @@ 4B723E1326B0007A00E14D75 /* CSVLoginExporter.swift in Sources */, B6BCC51E2AFCD9ED002C5499 /* DataImportSourcePicker.swift in Sources */, 85C48CCC278D808F00D3263E /* NSAttributedStringExtension.swift in Sources */, + 7B5A236F2C46A116007213AC /* ExcludedDomainsModel.swift in Sources */, 1D710F4B2C48F1F200C3975F /* UpdateDialogHelper.swift in Sources */, 4B41EDB42B168C55001EEDF4 /* VPNFeedbackFormViewModel.swift in Sources */, AA7EB6E527E7D6DC00036718 /* AnimationView.swift in Sources */, @@ -11955,6 +12021,7 @@ 1456D6E124EFCBC300775049 /* TabBarCollectionView.swift in Sources */, 4B4D60BF2A0C848A00BCD287 /* NetworkProtection+ConvenienceInitializers.swift in Sources */, 4B6B64842BA930420009FF9F /* WaitlistThankYouPromptPresenter.swift in Sources */, + 7B5A23682C468233007213AC /* ExcludedDomainsViewController.swift in Sources */, BDA7647C2BC497BE00D0400C /* DefaultVPNLocationFormatter.swift in Sources */, 3158B1592B0BF76400AF130C /* DataBrokerProtectionFeatureDisabler.swift in Sources */, B655124829A79465009BFE1C /* NavigationActionExtension.swift in Sources */, @@ -12058,6 +12125,7 @@ 37534CA8281198CD002621E7 /* AdjacentItemEnumerator.swift in Sources */, 7B7FCD0F2BA33B2700C04FBE /* UserDefaults+vpnLegacyUser.swift in Sources */, 987799F62999996B005D8EB6 /* BookmarkDatabase.swift in Sources */, + 7BB4BC6A2C5CD96200E06FC8 /* ActiveDomainPublisher.swift in Sources */, 4BE53374286E39F10019DBFD /* ChromiumKeychainPrompt.swift in Sources */, B6553692268440D700085A79 /* WKProcessPool+GeolocationProvider.swift in Sources */, B68D21C32ACBC916002DA3C2 /* ContentBlockingMock.swift in Sources */, @@ -13364,7 +13432,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 180.0.0; + version = "180.0.0-1"; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index d08cec1c367..743c6b243be 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "92ecebfb4172ab9561959a07d7ef7037aea8c6e1", - "version" : "180.0.0" + "revision" : "1dabef4fd0afa84317625d8327ee2bf30b173872", + "version" : "180.0.0-1" } }, { diff --git a/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser App Store.xcscheme b/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser App Store.xcscheme index e343e06df9f..7e937b1eb2f 100644 --- a/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser App Store.xcscheme +++ b/DuckDuckGo.xcodeproj/xcshareddata/xcschemes/DuckDuckGo Privacy Browser App Store.xcscheme @@ -145,6 +145,12 @@ + + + + + + + + Void private var didFinishLaunching = false @@ -109,7 +112,9 @@ final class URLEventHandler { private static func openURL(_ url: URL) { if url.scheme?.isNetworkProtectionScheme == true { - handleNetworkProtectionURL(url) + Task { @MainActor in + await vpnURLEventHandler.handle(url) + } } #if DBP @@ -141,38 +146,6 @@ final class URLEventHandler { } } - /// Handles NetP URLs - private static func handleNetworkProtectionURL(_ url: URL) { - DispatchQueue.main.async { - switch url { - case VPNAppLaunchCommand.showStatus.launchURL: - Task { - await WindowControllersManager.shared.showNetworkProtectionStatus() - } - case VPNAppLaunchCommand.showSettings.launchURL: - WindowControllersManager.shared.showPreferencesTab(withSelectedPane: .vpn) - case VPNAppLaunchCommand.shareFeedback.launchURL: - WindowControllersManager.shared.showShareFeedbackModal() - case VPNAppLaunchCommand.justOpen.launchURL: - WindowControllersManager.shared.showMainWindow() - case VPNAppLaunchCommand.showVPNLocations.launchURL: - WindowControllersManager.shared.showPreferencesTab(withSelectedPane: .vpn) - WindowControllersManager.shared.showLocationPickerSheet() - case VPNAppLaunchCommand.showPrivacyPro.launchURL: - let url = Application.appDelegate.subscriptionManager.url(for: .purchase) - WindowControllersManager.shared.showTab(with: .subscription(url)) - PixelKit.fire(PrivacyProPixel.privacyProOfferScreenImpression) -#if !APPSTORE && !DEBUG - case VPNAppLaunchCommand.moveAppToApplications.launchURL: - // this should be run after NSApplication.shared is set - PFMoveToApplicationsFolderIfNecessary(false) -#endif - default: - return - } - } - } - #if DBP /// Handles DBP URLs /// diff --git a/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift b/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift index 99d6f49afa7..4d8c4d348b0 100644 --- a/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift +++ b/DuckDuckGo/Common/Localizables/UserText+NetworkProtection.swift @@ -124,6 +124,8 @@ extension UserText { // MARK: - Setting Titles // "vpn.location.title" - Location section title in VPN settings static let vpnLocationTitle = "Location" + // "vpn.excluded.sites.title" - Excluded Sites title in VPN settings + static let vpnExcludedSitesTitle = "Excluded Sites" // "vpn.general.title" - General section title in VPN settings static let vpnGeneralTitle = "General" // "vpn.shortcuts.settings.title" - Shortcuts section title in VPN settings @@ -161,6 +163,16 @@ extension UserText { return String(format: message, count) } + // MARK: - Excluded Domains + // "vpn.setting.excluded.domains.description" - Excluded Sites description + static let vpnExcludedDomainsDescription = "Websites you selected to be excluded even when the VPN is connected." + // "vpn.setting.excluded.domains.manage.button.title" - Excluded Sites management button title + static let vpnExcludedDomainsManageButtonTitle = "Manage Excluded Sites…" + // "vpn.excluded.domains.add.domain" - Add Domain button for the excluded sites view + static let vpnExcludedDomainsAddDomain = "Add Website" + // "vpn.excluded.domains.title" - Title for the excluded sites view + static let vpnExcludedDomainsTitle = "Excluded Websites" + // MARK: - DNS // "vpn.dns.server.title" - Title of the DNS Server section static let vpnDnsServerTitle = "DNS Server" diff --git a/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift b/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift index 10e3549432c..b92afe8eac1 100644 --- a/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift +++ b/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift @@ -29,6 +29,7 @@ protocol PopoverPresenter { func show(_ popover: NSPopover, positionedBelow view: NSView) } +@MainActor protocol NetPPopoverManager: AnyObject { var isShown: Bool { get } @@ -133,8 +134,10 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter { } func toggleNetworkProtectionPopover(from button: MouseOverButton, withDelegate delegate: NSPopoverDelegate) { - if let popover = networkProtectionPopoverManager.toggle(positionedBelow: button, withDelegate: delegate) { - bindIsMouseDownState(of: button, to: popover) + Task { @MainActor in + if let popover = networkProtectionPopoverManager.toggle(positionedBelow: button, withDelegate: delegate) { + bindIsMouseDownState(of: button, to: popover) + } } } @@ -199,8 +202,10 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter { downloadsPopover?.close() } - if networkProtectionPopoverManager.isShown { - networkProtectionPopoverManager.close() + Task { @MainActor in + if networkProtectionPopoverManager.isShown { + networkProtectionPopoverManager.close() + } } if bookmarkPopover?.isShown ?? false { @@ -432,8 +437,11 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter { // MARK: - VPN func showNetworkProtectionPopover(positionedBelow button: MouseOverButton, withDelegate delegate: NSPopoverDelegate) { - let popover = networkProtectionPopoverManager.show(positionedBelow: button, withDelegate: delegate) - bindIsMouseDownState(of: button, to: popover) + + Task { @MainActor in + let popover = networkProtectionPopoverManager.show(positionedBelow: button, withDelegate: delegate) + bindIsMouseDownState(of: button, to: popover) + } } } diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/ActiveDomainPublisher.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/ActiveDomainPublisher.swift new file mode 100644 index 00000000000..9caf65a9ec2 --- /dev/null +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/ActiveDomainPublisher.swift @@ -0,0 +1,100 @@ +// +// ActiveDomainPublisher.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine +import Foundation + +/// A convenience class for publishing the active domain +/// +/// The active domain is the domain loaded in the last active tab within the last active window. +/// +final class ActiveDomainPublisher { + + private let windowControllersManager: WindowControllersManager + private var activeWindowControllerCancellable: AnyCancellable? + private var activeTabViewModelCancellable: AnyCancellable? + private var activeTabContentCancellable: AnyCancellable? + + @MainActor + @Published + private var activeWindowController: MainWindowController? { + didSet { + subscribeToActiveTabViewModel() + } + } + + @MainActor + @Published + private var activeTab: Tab? { + didSet { + subscribeToActiveTabContentChanges() + } + } + + init(windowControllersManager: WindowControllersManager) { + self.windowControllersManager = windowControllersManager + + Task { @MainActor in + subscribeToKeyWindowControllerChanges() + } + } + + @Published + private(set) var activeDomain: String? + + @MainActor + private func subscribeToKeyWindowControllerChanges() { + activeWindowControllerCancellable = windowControllersManager + .didChangeKeyWindowController + .prepend(windowControllersManager.lastKeyMainWindowController) + .assign(to: \.activeWindowController, onWeaklyHeld: self) + } + + @MainActor + private func subscribeToActiveTabViewModel() { + activeTabViewModelCancellable = activeWindowController?.mainViewController.tabCollectionViewModel.$selectedTabViewModel + .map(\.?.tab) + .assign(to: \.activeTab, onWeaklyHeld: self) + } + + @MainActor + private func subscribeToActiveTabContentChanges() { + activeTabContentCancellable = activeTab?.$content + .map(domain(from:)) + .removeDuplicates() + .assign(to: \.activeDomain, onWeaklyHeld: self) + } + + private func domain(from tabContent: Tab.TabContent) -> String? { + if case .url(let url, _, _) = tabContent { + + return url.host + } else { + return nil + } + } +} + +extension ActiveDomainPublisher: Publisher { + typealias Output = String? + typealias Failure = Never + + func receive(subscriber: S) where S: Subscriber, Never == S.Failure, String? == S.Input { + $activeDomain.subscribe(subscriber) + } +} diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift index 3bc4345a919..9afbacf5195 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugMenu.swift @@ -82,6 +82,14 @@ final class NetworkProtectionDebugMenu: NSMenu { NSMenuItem.separator() + NSMenuItem(title: "Adapter") { + NSMenuItem(title: "Restart Adapter", action: #selector(NetworkProtectionDebugMenu.restartAdapter(_:))) + .targetting(self) + + NSMenuItem(title: "Re-create Adapter", action: #selector(NetworkProtectionDebugMenu.restartAdapter(_:))) + .targetting(self) + } + NSMenuItem(title: "Tunnel Settings") { shouldIncludeAllNetworksMenuItem .targetting(self) @@ -218,6 +226,18 @@ final class NetworkProtectionDebugMenu: NSMenu { } } + /// Removes the system extension and agents for DuckDuckGo VPN. + /// + @objc func restartAdapter(_ sender: Any?) { + Task { @MainActor in + do { + try await debugUtilities.restartAdapter() + } catch { + await NSAlert(error: error).runModal() + } + } + } + /// Sends a test user notification. /// @objc func sendTestNotification(_ sender: Any?) { @@ -449,8 +469,8 @@ final class NetworkProtectionDebugMenu: NSMenu { private let ddgBrowserAppIdentifier = Bundle.main.bundleIdentifier! private func updateExclusionsMenu() { - excludeDBPTrafficFromVPN.state = transparentProxySettings.isExcluding(dbpBackgroundAppIdentifier) ? .on : .off - excludeDDGBrowserTrafficFromVPN.state = transparentProxySettings.isExcluding(ddgBrowserAppIdentifier) ? .on : .off + excludeDBPTrafficFromVPN.state = transparentProxySettings.isExcluding(appIdentifier: dbpBackgroundAppIdentifier) ? .on : .off + excludeDDGBrowserTrafficFromVPN.state = transparentProxySettings.isExcluding(appIdentifier: ddgBrowserAppIdentifier) ? .on : .off } @objc private func toggleExcludeDBPBackgroundAgent() { diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift index 8f3a0857346..d8d744f6849 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionDebugUtilities.swift @@ -54,6 +54,10 @@ final class NetworkProtectionDebugUtilities { // MARK: - Debug commands for the extension + func restartAdapter() async throws { + try await ipcClient.command(.restartAdapter) + } + func resetAllState(keepAuthToken: Bool) async throws { try await vpnUninstaller.uninstall(removeSystemExtension: true) diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift index 6b553616113..6573e3a550c 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionNavBarPopoverManager.swift @@ -19,6 +19,7 @@ import AppLauncher import AppKit import Combine +import Common import Foundation import LoginItems import NetworkProtection @@ -26,6 +27,8 @@ import NetworkProtectionIPC import NetworkProtectionUI import Subscription import VPNAppLauncher +import SwiftUI +import NetworkProtectionProxy protocol NetworkProtectionIPCClient { var ipcStatusObserver: ConnectionStatusObserver { get } @@ -44,15 +47,36 @@ extension VPNControllerXPCClient: NetworkProtectionIPCClient { public var ipcDataVolumeObserver: any NetworkProtection.DataVolumeObserver { dataVolumeObserver } } +@MainActor final class NetworkProtectionNavBarPopoverManager: NetPPopoverManager { private var networkProtectionPopover: NetworkProtectionPopover? let ipcClient: NetworkProtectionIPCClient let vpnUninstaller: VPNUninstalling + @Published + private var siteInfo: SiteTroubleshootingInfo? + private let siteTroubleshootingInfoPublisher: SiteTroubleshootingInfoPublisher + private var cancellables = Set() + init(ipcClient: VPNControllerXPCClient, vpnUninstaller: VPNUninstalling) { + self.ipcClient = ipcClient self.vpnUninstaller = vpnUninstaller + + let activeDomainPublisher = ActiveDomainPublisher(windowControllersManager: .shared) + + siteTroubleshootingInfoPublisher = SiteTroubleshootingInfoPublisher( + activeDomainPublisher: activeDomainPublisher.eraseToAnyPublisher(), + proxySettings: TransparentProxySettings(defaults: .netP)) + + subscribeToCurrentSitePublisher() + } + + private func subscribeToCurrentSitePublisher() { + siteTroubleshootingInfoPublisher + .assign(to: \.siteInfo, onWeaklyHeld: self) + .store(in: &cancellables) } var isShown: Bool { @@ -60,8 +84,7 @@ final class NetworkProtectionNavBarPopoverManager: NetPPopoverManager { } func show(positionedBelow view: NSView, withDelegate delegate: NSPopoverDelegate) -> NSPopover { - let popover = { - + let popover: NSPopover = { let controller = NetworkProtectionIPCTunnelController(ipcClient: ipcClient) let statusReporter = DefaultNetworkProtectionStatusReporter( @@ -77,12 +100,23 @@ final class NetworkProtectionNavBarPopoverManager: NetPPopoverManager { let onboardingStatusPublisher = UserDefaults.netP.networkProtectionOnboardingStatusPublisher _ = VPNSettings(defaults: .netP) let appLauncher = AppLauncher(appBundleURL: Bundle.main.bundleURL) - - let popover = NetworkProtectionPopover(controller: controller, - onboardingStatusPublisher: onboardingStatusPublisher, - statusReporter: statusReporter, - uiActionHandler: appLauncher, - menuItems: { + let vpnURLEventHandler = VPNURLEventHandler() + let proxySettings = TransparentProxySettings(defaults: .netP) + let uiActionHandler = VPNUIActionHandler(vpnURLEventHandler: vpnURLEventHandler, proxySettings: proxySettings) + + let siteTroubleshootingFeatureFlagPublisher = NSApp.delegateTyped.internalUserDecider.isInternalUserPublisher.eraseToAnyPublisher() + + let siteTroubleshootingViewModel = SiteTroubleshootingView.Model( + featureFlagPublisher: siteTroubleshootingFeatureFlagPublisher, + connectionStatusPublisher: statusReporter.statusObserver.publisher, + siteTroubleshootingInfoPublisher: $siteInfo.eraseToAnyPublisher(), + uiActionHandler: uiActionHandler) + + let statusViewModel = NetworkProtectionStatusView.Model(controller: controller, + onboardingStatusPublisher: onboardingStatusPublisher, + statusReporter: statusReporter, + uiActionHandler: uiActionHandler, + menuItems: { if UserDefaults.netP.networkProtectionOnboardingStatus == .completed { return [ NetworkProtectionStatusView.Model.MenuItem( @@ -113,13 +147,19 @@ final class NetworkProtectionNavBarPopoverManager: NetPPopoverManager { ] } }, - agentLoginItem: LoginItem.vpnMenu, - isMenuBarStatusView: false, - userDefaults: .netP, - locationFormatter: DefaultVPNLocationFormatter(), - uninstallHandler: { [weak self] in + agentLoginItem: LoginItem.vpnMenu, + isMenuBarStatusView: false, + userDefaults: .netP, + locationFormatter: DefaultVPNLocationFormatter(), + uninstallHandler: { [weak self] in _ = try? await self?.vpnUninstaller.uninstall(removeSystemExtension: true) }) + + let popover = NetworkProtectionPopover( + statusViewModel: statusViewModel, + statusReporter: statusReporter, + siteTroubleshootingViewModel: siteTroubleshootingViewModel, + debugInformationViewModel: DebugInformationViewModel(showDebugInformation: false)) popover.delegate = delegate networkProtectionPopover = popover diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift index 899897dfcea..78d6cda52f7 100644 --- a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/NetworkProtectionTunnelController.swift @@ -111,13 +111,6 @@ final class NetworkProtectionTunnelController: TunnelController, TunnelSessionPr // MARK: - User Defaults - /* Temporarily disabled - https://app.asana.com/0/0/1205766100762904/f - /// Test setting to exclude duckduckgo route from VPN - @MainActor - @UserDefaultsWrapper(key: .networkProtectionExcludedRoutes, defaultValue: [:]) - private(set) var excludedRoutesPreferences: [String: Bool] - */ - @UserDefaultsWrapper(key: .networkProtectionOnboardingStatusRawValue, defaultValue: OnboardingStatus.default.rawValue, defaults: .netP) private(set) var onboardingStatusRawValue: OnboardingStatus.RawValue diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/SiteTroubleshootingInfoPublisher.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/SiteTroubleshootingInfoPublisher.swift new file mode 100644 index 00000000000..5a3d5684148 --- /dev/null +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/SiteTroubleshootingInfoPublisher.swift @@ -0,0 +1,111 @@ +// +// SiteTroubleshootingInfoPublisher.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine +import Foundation +import NetworkProtectionProxy +import NetworkProtectionUI + +@MainActor +final class SiteTroubleshootingInfoPublisher { + + private var activeDomain: String? { + didSet { + refreshSiteTroubleshootingInfo() + } + } + + private let subject: CurrentValueSubject + + private let activeDomainPublisher: AnyPublisher + private let proxySettings: TransparentProxySettings + private var cancellables = Set() + + init(activeDomainPublisher: AnyPublisher, + proxySettings: TransparentProxySettings) { + + subject = CurrentValueSubject(nil) + self.activeDomainPublisher = activeDomainPublisher + self.proxySettings = proxySettings + + subscribeToActiveDomainChanges() + subscribeToExclusionChanges() + } + + private func subscribeToActiveDomainChanges() { + activeDomainPublisher + .assign(to: \.activeDomain, onWeaklyHeld: self) + .store(in: &cancellables) + } + + private func subscribeToExclusionChanges() { + proxySettings.changePublisher.sink { [weak self] change in + guard let self else { return } + + switch change { + case .excludedDomains: + refreshSiteTroubleshootingInfo() + default: + break + } + }.store(in: &cancellables) + } + + // MARK: - Refreshing + + func refreshSiteTroubleshootingInfo() { + if activeSiteTroubleshootingInfo != subject.value { + subject.send(activeSiteTroubleshootingInfo) + } + } + + // MARK: - Active Site Troubleshooting Info + + var activeSiteTroubleshootingInfo: SiteTroubleshootingInfo? { + guard let activeDomain else { + return nil + } + + return site(forDomain: activeDomain.droppingWwwPrefix()) + } + + private func site(forDomain domain: String) -> SiteTroubleshootingInfo? { + let icon: NSImage? + let currentSite: NetworkProtectionUI.SiteTroubleshootingInfo? + + icon = FaviconManager.shared.getCachedFavicon(for: domain, sizeCategory: .small)?.image + let proxySettings = TransparentProxySettings(defaults: .netP) + currentSite = NetworkProtectionUI.SiteTroubleshootingInfo( + icon: icon, + domain: domain, + excluded: proxySettings.isExcluding(domain: domain)) + + return currentSite + } +} + +extension SiteTroubleshootingInfoPublisher: Publisher { + typealias Output = SiteTroubleshootingInfo? + typealias Failure = Never + + nonisolated + func receive(subscriber: S) where S: Subscriber, Never == S.Failure, NetworkProtectionUI.SiteTroubleshootingInfo? == S.Input { + + subject.receive(subscriber: subscriber) + } +} diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNUIActionHandler.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNUIActionHandler.swift new file mode 100644 index 00000000000..53db14808bd --- /dev/null +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNUIActionHandler.swift @@ -0,0 +1,65 @@ +// +// VPNUIActionHandler.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import AppLauncher +import Foundation +import NetworkProtectionIPC +import NetworkProtectionProxy +import NetworkProtectionUI +import VPNAppLauncher + +/// Main App's VPN UI action handler +/// +final class VPNUIActionHandler: VPNUIActionHandling { + + private let vpnIPCClient: VPNControllerXPCClient + private let proxySettings: TransparentProxySettings + private let vpnURLEventHandler: VPNURLEventHandler + + init(vpnIPCClient: VPNControllerXPCClient = .shared, + vpnURLEventHandler: VPNURLEventHandler, + proxySettings: TransparentProxySettings) { + + self.vpnIPCClient = vpnIPCClient + self.vpnURLEventHandler = vpnURLEventHandler + self.proxySettings = proxySettings + } + + public func moveAppToApplications() async { +#if !APPSTORE && !DEBUG + await vpnURLEventHandler.moveAppToApplicationsFolder() +#endif + } + + func setExclusion(_ exclude: Bool, forDomain domain: String) async { + proxySettings.setExclusion(exclude, forDomain: domain) + try? await vpnIPCClient.command(.restartAdapter) + } + + public func shareFeedback() async { + await vpnURLEventHandler.showShareFeedback() + } + + public func showVPNLocations() async { + await vpnURLEventHandler.showLocations() + } + + public func showPrivacyPro() async { + await vpnURLEventHandler.showPrivacyPro() + } +} diff --git a/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNURLEventHandler.swift b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNURLEventHandler.swift new file mode 100644 index 00000000000..54368bc09e1 --- /dev/null +++ b/DuckDuckGo/NetworkProtection/AppTargets/BothAppTargets/VPNURLEventHandler.swift @@ -0,0 +1,91 @@ +// +// VPNURLEventHandler.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import PixelKit +import VPNAppLauncher + +@MainActor +final class VPNURLEventHandler { + + private let windowControllerManager: WindowControllersManager + + init(windowControllerManager: WindowControllersManager? = nil) { + self.windowControllerManager = windowControllerManager ?? .shared + } + + /// Handles VPN event URLs + /// + func handle(_ url: URL) async { + switch url { + case VPNAppLaunchCommand.showStatus.launchURL: + await showStatus() + case VPNAppLaunchCommand.showSettings.launchURL: + showPreferences() + case VPNAppLaunchCommand.shareFeedback.launchURL: + showShareFeedback() + case VPNAppLaunchCommand.justOpen.launchURL: + showMainWindow() + case VPNAppLaunchCommand.showVPNLocations.launchURL: + showLocations() + case VPNAppLaunchCommand.showPrivacyPro.launchURL: + showPrivacyPro() +#if !APPSTORE && !DEBUG + case VPNAppLaunchCommand.moveAppToApplications.launchURL: + moveAppToApplicationsFolder() +#endif + default: + return + } + } + + func showStatus() async { + await windowControllerManager.showNetworkProtectionStatus() + } + + func showPreferences() { + windowControllerManager.showPreferencesTab(withSelectedPane: .vpn) + } + + func showShareFeedback() { + windowControllerManager.showShareFeedbackModal() + } + + func showMainWindow() { + windowControllerManager.showMainWindow() + } + + func showLocations() { + windowControllerManager.showPreferencesTab(withSelectedPane: .vpn) + windowControllerManager.showLocationPickerSheet() + } + + func showPrivacyPro() { + let url = Application.appDelegate.subscriptionManager.url(for: .purchase) + windowControllerManager.showTab(with: .subscription(url)) + + PixelKit.fire(PrivacyProPixel.privacyProOfferScreenImpression) + } + +#if !APPSTORE && !DEBUG + func moveAppToApplicationsFolder() { + // this should be run after NSApplication.shared is set + PFMoveToApplicationsFolderIfNecessary(false) + } +#endif +} diff --git a/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainButtonsView.swift b/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainButtonsView.swift new file mode 100644 index 00000000000..c4db9dafc0f --- /dev/null +++ b/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainButtonsView.swift @@ -0,0 +1,187 @@ +// +// AddExcludedDomainButtonsView.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import SwiftUI + +struct AddExcludedDomainButtonsView: View { + private let viewState: ViewState + private let otherButtonAction: Action + private let defaultButtonAction: Action + @Environment(\.dismiss) private var dismiss + + init( + viewState: ViewState, + otherButtonAction: Action, + defaultButtonAction: Action + ) { + self.viewState = viewState + self.otherButtonAction = otherButtonAction + self.defaultButtonAction = defaultButtonAction + } + + var body: some View { + HStack { + if viewState == .compressed { + Spacer() + } + + actionButton(action: otherButtonAction, viewState: viewState).accessibilityIdentifier("AddExcludedDomainButtonsView.otherButton") + + actionButton(action: defaultButtonAction, viewState: viewState).accessibilityIdentifier("AddExcludedDomainButtonsView.defaultButton") + } + } + + @MainActor + private func actionButton(action: Action, viewState: ViewState) -> some View { + Button { + action.action(dismiss.callAsFunction) + } label: { + Text(action.title) + .frame(height: viewState.height) + .frame(maxWidth: viewState.maxWidth) + } + .keyboardShortcut(action.keyboardShortCut) + .disabled(action.isDisabled) + .ifLet(action.accessibilityIdentifier) { view, value in + view.accessibilityIdentifier(value) + } + } +} + +// MARK: - BookmarkDialogButtonsView + Types + +extension AddExcludedDomainButtonsView { + + enum ViewState: Equatable { + case compressed + case expanded + } + + struct Action { + let title: String + let keyboardShortCut: KeyboardShortcut? + let accessibilityIdentifier: String? + let isDisabled: Bool + let action: @MainActor (_ dismiss: () -> Void) -> Void + + init( + title: String, + accessibilityIdentifier: String? = nil, + keyboardShortCut: KeyboardShortcut? = nil, + isDisabled: Bool = false, + action: @MainActor @escaping (_ dismiss: () -> Void) -> Void + ) { + self.title = title + self.keyboardShortCut = keyboardShortCut + self.accessibilityIdentifier = accessibilityIdentifier + self.isDisabled = isDisabled + self.action = action + } + } +} + +// MARK: - BookmarkDialogButtonsView.ViewState + +private extension AddExcludedDomainButtonsView.ViewState { + + var maxWidth: CGFloat? { + switch self { + case .compressed: + return nil + case .expanded: + return .infinity + } + } + + var height: CGFloat? { + switch self { + case .compressed: + return nil + case .expanded: + return 28.0 + } + } + +} + +// MARK: - Preview + +#Preview("Compressed - Disable Default Button") { + AddExcludedDomainButtonsView( + viewState: .compressed, + otherButtonAction: .init( + title: "Left", + action: { _ in } + ), + defaultButtonAction: .init( + title: "Right", + isDisabled: true, + action: {_ in } + ) + ) + .frame(width: 320, height: 50) +} + +#Preview("Compressed - Enabled Default Button") { + AddExcludedDomainButtonsView( + viewState: .compressed, + otherButtonAction: .init( + title: "Left", + action: { _ in } + ), + defaultButtonAction: .init( + title: "Right", + isDisabled: false, + action: {_ in } + ) + ) + .frame(width: 320, height: 50) +} + +#Preview("Expanded - Disable Default Button") { + AddExcludedDomainButtonsView( + viewState: .expanded, + otherButtonAction: .init( + title: "Left", + action: { _ in } + ), + defaultButtonAction: .init( + title: "Right", + isDisabled: true, + action: {_ in } + ) + ) + .frame(width: 320, height: 50) +} + +#Preview("Expanded - Enable Default Button") { + AddExcludedDomainButtonsView( + viewState: .expanded, + otherButtonAction: .init( + title: "Left", + action: { _ in } + ), + defaultButtonAction: .init( + title: "Right", + isDisabled: false, + action: {_ in } + ) + ) + .frame(width: 320, height: 50) +} diff --git a/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainView.swift b/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainView.swift new file mode 100644 index 00000000000..d79d26d0d1f --- /dev/null +++ b/DuckDuckGo/NetworkProtection/ExcludedDomains/AddExcludedDomainView.swift @@ -0,0 +1,112 @@ +// +// AddExcludedDomainView.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import SwiftUI +import SwiftUIExtensions + +struct AddExcludedDomainView: ModalView { + enum ButtonsState { + case compressed + case expanded + } + + let title: String + let buttonsState: ButtonsState + + @State + private var domain = "" + + let cancelActionTitle: String + let cancelAction: @MainActor (_ dismiss: () -> Void) -> Void + + let defaultActionTitle: String + @State + private var isDefaultActionDisabled = true + let defaultAction: @MainActor (_ domain: String, _ dismiss: () -> Void) -> Void + + var body: some View { + TieredDialogView( + verticalSpacing: 16.0, + horizontalPadding: 20.0, + top: { + Text(title) + .foregroundColor(.primary) + .fontWeight(.semibold) + .padding(.top, 20) + }, + center: { + form + }, + bottom: { + AddExcludedDomainButtonsView( + viewState: .init(buttonsState), + otherButtonAction: .init( + title: cancelActionTitle, + keyboardShortCut: .cancelAction, + isDisabled: false, + action: cancelAction + ), defaultButtonAction: .init( + title: defaultActionTitle, + keyboardShortCut: .defaultAction, + isDisabled: isDefaultActionDisabled, + action: { dismiss in + defaultAction(domain, dismiss) + } + ) + ).padding(.bottom, 16.0) + } + ).font(.system(size: 13)) + .frame(width: 420) + } + + var form: some View { + TwoColumnsListView( + horizontalSpacing: 16.0, + verticalSpacing: 20.0, + rowHeight: 22.0, + leftColumn: { + Text("URL") + .foregroundColor(.primary) + .fontWeight(.medium) + }, + rightColumn: { + TextField("", text: $domain) + .focusedOnAppear() + .onChange(of: domain) { _ in + isDefaultActionDisabled = !domain.isValidHostname + } + .accessibilityIdentifier("bookmark.add.name.textfield") + .textFieldStyle(RoundedBorderTextFieldStyle()) + .font(.system(size: 14)) + } + ) + } +} + +private extension AddExcludedDomainButtonsView.ViewState { + + init(_ state: AddExcludedDomainView.ButtonsState) { + switch state { + case .compressed: + self = .compressed + case .expanded: + self = .expanded + } + } +} diff --git a/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomains.storyboard b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomains.storyboard new file mode 100644 index 00000000000..30ffd0b64fb --- /dev/null +++ b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomains.storyboard @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsModel.swift b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsModel.swift new file mode 100644 index 00000000000..b3cbdbd75ea --- /dev/null +++ b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsModel.swift @@ -0,0 +1,54 @@ +// +// ExcludedDomainsModel.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import NetworkProtectionProxy + +protocol ExcludedDomainsViewModel { + var domains: [String] { get } + + func add(domain: String) + func remove(domain: String) +} + +final class DefaultExcludedDomainsViewModel { + let proxySettings = TransparentProxySettings(defaults: .netP) + + init() { + } +} + +extension DefaultExcludedDomainsViewModel: ExcludedDomainsViewModel { + var domains: [String] { + proxySettings.excludedDomains + } + + func add(domain: String) { + guard !proxySettings.excludedDomains.contains(domain) else { + return + } + + proxySettings.excludedDomains.append(domain) + } + + func remove(domain: String) { + proxySettings.excludedDomains.removeAll { cursor in + domain == cursor + } + } +} diff --git a/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsViewController.swift b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsViewController.swift new file mode 100644 index 00000000000..6192405f211 --- /dev/null +++ b/DuckDuckGo/NetworkProtection/ExcludedDomains/ExcludedDomainsViewController.swift @@ -0,0 +1,178 @@ +// +// ExcludedDomainsViewController.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import AppKit + +final class ExcludedDomainsViewController: NSViewController { + typealias Model = ExcludedDomainsViewModel + + enum Constants { + static let storyboardName = "ExcludedDomains" + static let identifier = "ExcludedDomainsViewController" + static let cellIdentifier = NSUserInterfaceItemIdentifier(rawValue: "ExcludedDomainCell") + } + + static func create(model: Model = DefaultExcludedDomainsViewModel()) -> ExcludedDomainsViewController { + let storyboard = loadStoryboard() + + return storyboard.instantiateController(identifier: Constants.identifier) { coder in + ExcludedDomainsViewController(model: model, coder: coder) + } + } + + static func loadStoryboard() -> NSStoryboard { + NSStoryboard(name: Constants.storyboardName, bundle: nil) + } + + @IBOutlet var tableView: NSTableView! + @IBOutlet var addDomainButton: NSButton! + @IBOutlet var removeDomainButton: NSButton! + @IBOutlet var doneButton: NSButton! + @IBOutlet var excludedDomainsLabel: NSTextField! + + private let faviconManagement: FaviconManagement = FaviconManager.shared + + private var allDomains = [String]() + private var filteredDomains: [String]? + + private var visibleDomains: [String] { + return filteredDomains ?? allDomains + } + + private let model: Model + + init?(model: Model, coder: NSCoder) { + self.model = model + + super.init(coder: coder) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + override func viewDidLoad() { + super.viewDidLoad() + + applyModalWindowStyleIfNeeded() + reloadData() + setUpStrings() + } + + private func setUpStrings() { + addDomainButton.title = UserText.vpnExcludedDomainsAddDomain + removeDomainButton.title = UserText.remove + doneButton.title = UserText.done + excludedDomainsLabel.stringValue = UserText.vpnExcludedDomainsTitle + } + + private func updateRemoveButtonState() { + removeDomainButton.isEnabled = tableView.selectedRow > -1 + } + + fileprivate func reloadData() { + allDomains = model.domains.sorted { (lhs, rhs) -> Bool in + return lhs < rhs + } + + tableView.reloadData() + updateRemoveButtonState() + } + + @IBAction func doneButtonClicked(_ sender: NSButton) { + dismiss() + } + + @IBAction func addDomain(_ sender: NSButton) { + AddExcludedDomainView(title: "Add Website Exclusion", buttonsState: .compressed, cancelActionTitle: "Cancel", cancelAction: { dismiss in + + dismiss() + }, defaultActionTitle: "Add Website") { [weak self] domain, dismiss in + guard let self else { return } + + addDomain(domain) + dismiss() + }.show(in: view.window) + } + + private func addDomain(_ domain: String) { + model.add(domain: domain) + reloadData() + + if let newRowIndex = allDomains.firstIndex(of: domain) { + tableView.scrollRowToVisible(newRowIndex) + } + } + + @IBAction func removeSelectedDomain(_ sender: NSButton) { + guard tableView.selectedRow > -1 else { + updateRemoveButtonState() + return + } + + let selectedDomain = visibleDomains[tableView.selectedRow] + model.remove(domain: selectedDomain) + reloadData() + } +} + +extension ExcludedDomainsViewController: NSTableViewDataSource, NSTableViewDelegate { + + func numberOfRows(in tableView: NSTableView) -> Int { + return visibleDomains.count + } + + func tableView(_ tableView: NSTableView, objectValueFor tableColumn: NSTableColumn?, row: Int) -> Any? { + return visibleDomains[row] + } + + func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? { + guard let cell = tableView.makeView(withIdentifier: Constants.cellIdentifier, owner: nil) as? NSTableCellView else { + + return nil + } + + let domain = visibleDomains[row] + + cell.textField?.stringValue = domain + cell.imageView?.image = faviconManagement.getCachedFavicon(for: domain, sizeCategory: .small)?.image + cell.imageView?.applyFaviconStyle() + + return cell + } + + func tableViewSelectionDidChange(_ notification: Notification) { + updateRemoveButtonState() + } +} + +extension ExcludedDomainsViewController: NSTextFieldDelegate { + + func controlTextDidChange(_ notification: Notification) { + guard let field = notification.object as? NSSearchField else { return } + + if field.stringValue.isEmpty { + filteredDomains = nil + } else { + filteredDomains = allDomains.filter { $0.contains(field.stringValue) } + } + + reloadData() + } + +} diff --git a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift index 0e856edf95f..bf2e66e6642 100644 --- a/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift +++ b/DuckDuckGo/Preferences/Model/VPNPreferencesModel.swift @@ -20,6 +20,7 @@ import AppKit import Combine import Foundation import NetworkProtection +import NetworkProtectionIPC import NetworkProtectionUI import BrowserServicesKit @@ -38,6 +39,9 @@ final class VPNPreferencesModel: ObservableObject { @Published var excludeLocalNetworks: Bool { didSet { settings.excludeLocalNetworks = excludeLocalNetworks + Task { + try await vpnXPCClient.command(.restartAdapter) + } } } @@ -59,6 +63,13 @@ final class VPNPreferencesModel: ObservableObject { } } + /// Whether the excluded sites section in preferences is shown. + /// + /// Only necessary because this is feature flagged to internal users. + /// + @Published + var showExcludedSites: Bool + @Published var notifyStatusChanges: Bool { didSet { settings.notifyStatusChanges = notifyStatusChanges @@ -74,19 +85,25 @@ final class VPNPreferencesModel: ObservableObject { } @Published public var dnsSettings: NetworkProtectionDNSSettings = .default - @Published public var isCustomDNSSelected = false @Published public var customDNSServers: String? + private let vpnXPCClient: VPNControllerXPCClient private let settings: VPNSettings private let pinningManager: PinningManager + private let internalUserDecider: InternalUserDecider private var cancellables = Set() - init(settings: VPNSettings = .init(defaults: .netP), + init(vpnXPCClient: VPNControllerXPCClient = .shared, + settings: VPNSettings = .init(defaults: .netP), pinningManager: PinningManager = LocalPinningManager.shared, - defaults: UserDefaults = .netP) { + defaults: UserDefaults = .netP, + internalUserDecider: InternalUserDecider = NSApp.delegateTyped.internalUserDecider) { + + self.vpnXPCClient = vpnXPCClient self.settings = settings self.pinningManager = pinningManager + self.internalUserDecider = internalUserDecider connectOnLogin = settings.connectOnLogin excludeLocalNetworks = settings.excludeLocalNetworks @@ -94,6 +111,7 @@ final class VPNPreferencesModel: ObservableObject { showInMenuBar = settings.showInMenuBar showInBrowserToolbar = pinningManager.isPinned(.networkProtection) showUninstallVPN = defaults.networkProtectionOnboardingStatus != .default + showExcludedSites = internalUserDecider.isInternalUser onboardingStatus = defaults.networkProtectionOnboardingStatus locationItem = VPNLocationPreferenceItemModel(selectedLocation: settings.selectedLocation) @@ -102,6 +120,7 @@ final class VPNPreferencesModel: ObservableObject { subscribeToShowInBrowserToolbarSettingsChanges() subscribeToLocationSettingChanges() subscribeToDNSSettingsChanges() + subscribeToInternalUserChanges() } func subscribeToOnboardingStatusChanges(defaults: UserDefaults) { @@ -150,6 +169,12 @@ final class VPNPreferencesModel: ObservableObject { customDNSServers = settings.dnsSettings.dnsServersText } + private func subscribeToInternalUserChanges() { + internalUserDecider.isInternalUserPublisher + .assign(to: \.showExcludedSites, onWeaklyHeld: self) + .store(in: &cancellables) + } + func resetDNSSettings() { settings.dnsSettings = .default } @@ -182,6 +207,22 @@ final class VPNPreferencesModel: ObservableObject { return alert } + + // MARK: - Excluded Sites + + @MainActor + func manageExcludedSites() { + let windowController = ExcludedDomainsViewController.create().wrappedInWindowController() + + guard let window = windowController.window, + let parentWindowController = WindowControllersManager.shared.lastKeyMainWindowController + else { + assertionFailure("DataClearingPreferences: Failed to present ExcludedDomainsViewController") + return + } + + parentWindowController.window?.beginSheet(window) + } } extension NetworkProtectionDNSSettings { diff --git a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift index 10ef5fd0901..7d0c793bc29 100644 --- a/DuckDuckGo/Preferences/View/PreferencesVPNView.swift +++ b/DuckDuckGo/Preferences/View/PreferencesVPNView.swift @@ -55,7 +55,24 @@ extension Preferences { } .padding(.bottom, 12) - // SECTION: Manage VPN + // SECTION: Excluded Sites + + if model.showExcludedSites { + PreferencePaneSection(UserText.vpnExcludedSitesTitle, spacing: 4) { + Text(UserText.vpnExcludedDomainsDescription) + .foregroundColor(.secondary) + .padding(.bottom, 18) + + PreferencePaneSubSection { + Button(UserText.vpnExcludedDomainsManageButtonTitle) { + model.manageExcludedSites() + } + } + } + .padding(.bottom, 12) + } + + // SECTION: General PreferencePaneSection(UserText.vpnGeneralTitle) { diff --git a/DuckDuckGo/Tab/View/BrowserTabViewController.swift b/DuckDuckGo/Tab/View/BrowserTabViewController.swift index d9c696c8200..779e35dc471 100644 --- a/DuckDuckGo/Tab/View/BrowserTabViewController.swift +++ b/DuckDuckGo/Tab/View/BrowserTabViewController.swift @@ -1193,7 +1193,7 @@ extension BrowserTabViewController { private func subscribeToTabSelectedInCurrentKeyWindow() { let lastKeyWindowOtherThanOurs = WindowControllersManager.shared.didChangeKeyWindowController - .map { WindowControllersManager.shared.lastKeyMainWindowController } + .map { $0 } .prepend(WindowControllersManager.shared.lastKeyMainWindowController) .compactMap { $0 } .filter { [weak self] in $0.window !== self?.view.window } diff --git a/DuckDuckGo/Windows/View/WindowControllersManager.swift b/DuckDuckGo/Windows/View/WindowControllersManager.swift index f597e7432eb..e21c96bc99e 100644 --- a/DuckDuckGo/Windows/View/WindowControllersManager.swift +++ b/DuckDuckGo/Windows/View/WindowControllersManager.swift @@ -38,6 +38,10 @@ final class WindowControllersManager: WindowControllersManagerProtocol { static let shared = WindowControllersManager(pinnedTabsManager: Application.appDelegate.pinnedTabsManager) + var activeViewController: MainViewController? { + lastKeyMainWindowController?.mainViewController + } + init(pinnedTabsManager: PinnedTabsManager) { self.pinnedTabsManager = pinnedTabsManager } @@ -52,7 +56,7 @@ final class WindowControllersManager: WindowControllersManagerProtocol { weak var lastKeyMainWindowController: MainWindowController? { didSet { if lastKeyMainWindowController != oldValue { - didChangeKeyWindowController.send(()) + didChangeKeyWindowController.send(lastKeyMainWindowController) } } } @@ -69,7 +73,7 @@ final class WindowControllersManager: WindowControllersManagerProtocol { return mainWindowController?.mainViewController.tabCollectionViewModel.selectedTab } - let didChangeKeyWindowController = PassthroughSubject() + let didChangeKeyWindowController = PassthroughSubject() let didRegisterWindowController = PassthroughSubject<(MainWindowController), Never>() let didUnregisterWindowController = PassthroughSubject<(MainWindowController), Never>() diff --git a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift index 6a3e6c6f7f5..3b5d39600d8 100644 --- a/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift +++ b/DuckDuckGoVPN/DuckDuckGoVPNAppDelegate.swift @@ -75,7 +75,7 @@ final class DuckDuckGoVPNApplication: NSApplication { self.delegate = _delegate #if DEBUG - if let token = accountManager.accessToken { + if accountManager.accessToken != nil { os_log(.error, log: .networkProtection, "🟢 VPN Agent found token") } else { os_log(.error, log: .networkProtection, "🔴 VPN Agent found no token") @@ -311,6 +311,9 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { }.eraseToAnyPublisher() let model = StatusBarMenuModel(vpnSettings: .init(defaults: .netP)) + let uiActionHandler = VPNUIActionHandler( + appLauncher: appLauncher, + proxySettings: proxySettings) return StatusBarMenu( model: model, @@ -318,7 +321,7 @@ final class DuckDuckGoVPNAppDelegate: NSObject, NSApplicationDelegate { statusReporter: statusReporter, controller: tunnelController, iconProvider: iconProvider, - uiActionHandler: appLauncher, + uiActionHandler: uiActionHandler, menuItems: { [ StatusBarMenu.MenuItem(name: UserText.networkProtectionStatusMenuVPNSettings, action: { [weak self] in diff --git a/DuckDuckGoVPN/TunnelControllerIPCService.swift b/DuckDuckGoVPN/TunnelControllerIPCService.swift index 5052f99ca2c..c95c4fc0b1f 100644 --- a/DuckDuckGoVPN/TunnelControllerIPCService.swift +++ b/DuckDuckGoVPN/TunnelControllerIPCService.swift @@ -243,6 +243,9 @@ extension TunnelControllerIPCService: XPCServerInterface { break case .removeVPNConfiguration: try await uninstall(.configuration) + case .restartAdapter: + // Intentional no-op: handled by the extension + break case .uninstallVPN: try await uninstall(.all) case .disableConnectOnDemandAndShutDown: diff --git a/DuckDuckGoVPN/VPNUIActionHandler.swift b/DuckDuckGoVPN/VPNUIActionHandler.swift new file mode 100644 index 00000000000..dae739499c5 --- /dev/null +++ b/DuckDuckGoVPN/VPNUIActionHandler.swift @@ -0,0 +1,58 @@ +// +// VPNUIActionHandler.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import AppLauncher +import Foundation +import NetworkProtectionProxy +import NetworkProtectionUI +import VPNAppLauncher + +/// VPN Agent's UI action handler +/// +final class VPNUIActionHandler: VPNUIActionHandling { + + private let appLauncher: AppLauncher + private let proxySettings: TransparentProxySettings + + init(appLauncher: AppLauncher, proxySettings: TransparentProxySettings) { + self.appLauncher = appLauncher + self.proxySettings = proxySettings + } + + public func moveAppToApplications() async { +#if !APPSTORE && !DEBUG + try? await appLauncher.launchApp(withCommand: VPNAppLaunchCommand.moveAppToApplications) +#endif + } + + func setExclusion(_ exclude: Bool, forDomain domain: String) async { + proxySettings.setExclusion(exclude, forDomain: domain) + } + + public func shareFeedback() async { + try? await appLauncher.launchApp(withCommand: VPNAppLaunchCommand.shareFeedback) + } + + public func showVPNLocations() async { + try? await appLauncher.launchApp(withCommand: VPNAppLaunchCommand.showVPNLocations) + } + + public func showPrivacyPro() async { + try? await appLauncher.launchApp(withCommand: VPNAppLaunchCommand.showPrivacyPro) + } +} diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index 0da0593983e..df9462c043d 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0-1"), .package(path: "../SwiftUIExtensions"), .package(path: "../XPCHelper"), ], diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index 841f8ef5eb5..b3fdfe5e417 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -32,7 +32,7 @@ let package = Package( .library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0-1"), .package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"), .package(path: "../AppLauncher"), .package(path: "../UDSHelper"), diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/FlowManagers/TCPFlowManager.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/FlowManagers/TCPFlowManager.swift index 882eb197341..edf987d2018 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/FlowManagers/TCPFlowManager.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/FlowManagers/TCPFlowManager.swift @@ -30,20 +30,35 @@ struct TCPFlowActor { } @TCPFlowActor -enum RemoteConnectionError: Error { +enum RemoteConnectionError: CustomNSError { case complete case cancelled case couldNotEstablishConnection(_ error: Error) case unhandledError(_ error: Error) + + nonisolated + var errorUserInfo: [String: Any] { + switch self { + case .complete, + .cancelled: + return [:] + case .couldNotEstablishConnection(let error), + .unhandledError(let error): + return [NSUnderlyingErrorKey: error as NSError] + + } + } } final class TCPFlowManager { private let flow: NEAppProxyTCPFlow private var connectionTask: Task? private var connection: NWConnection? + private let logger: Logger - init(flow: NEAppProxyTCPFlow) { + init(flow: NEAppProxyTCPFlow, logger: Logger) { self.flow = flow + self.logger = logger } deinit { @@ -67,10 +82,13 @@ final class TCPFlowManager { do { try await startDataCopyLoop(for: remoteConnection) + logger.log("🔴 Stopping proxy connection to \(remoteEndpoint, privacy: .public)") remoteConnection.cancel() flow.closeReadWithError(nil) flow.closeWriteWithError(nil) } catch { + logger.log("🔴 Stopping proxy connection to \(remoteEndpoint, privacy: .public) with error \(String(reflecting: error), privacy: .public)") + remoteConnection.cancel() flow.closeReadWithError(error) flow.closeWriteWithError(error) diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/IPC/TransparentProxyAppMessageHandler.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/IPC/TransparentProxyAppMessageHandler.swift index 12339a673d7..988ffd1f77f 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/IPC/TransparentProxyAppMessageHandler.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/IPC/TransparentProxyAppMessageHandler.swift @@ -18,14 +18,18 @@ import Foundation import OSLog // swiftlint:disable:this enforce_os_log_wrapper +import NetworkExtension /// Handles app messages /// final class TransparentProxyAppMessageHandler { private let settings: TransparentProxySettings + private let logger: Logger - init(settings: TransparentProxySettings) { + init(settings: TransparentProxySettings, logger: Logger) { + + self.logger = logger self.settings = settings } @@ -48,11 +52,13 @@ final class TransparentProxyAppMessageHandler { await withCheckedContinuation { continuation in var request: TransparentProxyRequest + logger.log("Handling app message: \(String(describing: message), privacy: .public)") + switch message { case .changeSetting(let change): - request = .changeSetting(change, responseHandler: { + request = .changeSetting(change) { continuation.resume(returning: nil) - }) + } } handle(request) diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Settings/TransparentProxySettings.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Settings/TransparentProxySettings.swift index db010ec2b5d..ba8d98c243b 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Settings/TransparentProxySettings.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/Settings/TransparentProxySettings.swift @@ -79,16 +79,16 @@ public final class TransparentProxySettings { // MARK: - App routing rules logic - public func isBlocking(_ appIdentifier: String) -> Bool { + public func isBlocking(appIdentifier: String) -> Bool { appRoutingRules[appIdentifier] == .block } - public func isExcluding(_ appIdentifier: String) -> Bool { + public func isExcluding(appIdentifier: String) -> Bool { appRoutingRules[appIdentifier] == .exclude } public func toggleBlocking(for appIdentifier: String) { - if isBlocking(appIdentifier) { + if isBlocking(appIdentifier: appIdentifier) { appRoutingRules.removeValue(forKey: appIdentifier) } else { appRoutingRules[appIdentifier] = .block @@ -96,13 +96,43 @@ public final class TransparentProxySettings { } public func toggleExclusion(for appIdentifier: String) { - if isExcluding(appIdentifier) { + if isExcluding(appIdentifier: appIdentifier) { appRoutingRules.removeValue(forKey: appIdentifier) } else { appRoutingRules[appIdentifier] = .exclude } } + // MARK: - Domain Exclusions + + public func isExcluding(domain: String) -> Bool { + excludedDomains.contains(domain) + } + + public func setExclusion(_ exclude: Bool, forDomain domain: String) { + if exclude { + guard !isExcluding(domain: domain) else { + return + } + + excludedDomains.append(domain) + } else { + guard isExcluding(domain: domain) else { + return + } + + excludedDomains.removeAll { $0 == domain } + } + } + + public func toggleExclusion(domain: String) { + if isExcluding(domain: domain) { + excludedDomains.removeAll { $0 == domain } + } else { + excludedDomains.append(domain) + } + } + // MARK: - Snapshot support public func snapshot() -> TransparentProxySettingsSnapshot { diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/TransparentProxyProvider.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/TransparentProxyProvider.swift index 33b75fd73b9..c71dbc9ee18 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/TransparentProxyProvider.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionProxy/TransparentProxyProvider.swift @@ -16,6 +16,7 @@ // limitations under the License. // +import Combine import Foundation import NetworkExtension import NetworkProtection @@ -35,10 +36,10 @@ open class TransparentProxyProvider: NETransparentProxyProvider { static let dnsPort = 53 @TCPFlowActor - var tcpFlowManagers = Set() + private var tcpFlowManagers = Set() @UDPFlowActor - var udpFlowManagers = Set() + private var udpFlowManagers = Set() private let monitor = nw_path_monitor_create() var directInterface: nw_interface_t? @@ -46,6 +47,8 @@ open class TransparentProxyProvider: NETransparentProxyProvider { private let bMonitor = NWPathMonitor() var interface: NWInterface? + private var cancellables = Set() + public let configuration: Configuration public let settings: TransparentProxySettings @@ -54,8 +57,7 @@ open class TransparentProxyProvider: NETransparentProxyProvider { public var eventHandler: EventCallback? private let logger: Logger - - private lazy var appMessageHandler = TransparentProxyAppMessageHandler(settings: settings) + private let appMessageHandler: TransparentProxyAppMessageHandler // MARK: - Init @@ -63,10 +65,15 @@ open class TransparentProxyProvider: NETransparentProxyProvider { configuration: Configuration, logger: Logger) { + appMessageHandler = TransparentProxyAppMessageHandler(settings: settings, logger: logger) self.configuration = configuration self.logger = logger self.settings = settings + super.init() + + subscribeToSettings() + logger.debug("[+] \(String(describing: Self.self), privacy: .public)") } @@ -74,6 +81,21 @@ open class TransparentProxyProvider: NETransparentProxyProvider { logger.debug("[-] \(String(describing: Self.self), privacy: .public)") } + private func subscribeToSettings() { + settings.changePublisher.sink { change in + switch change { + case .appRoutingRules: + Task { + try await self.updateNetworkSettings() + } + case .excludedDomains: + Task { + try await self.updateNetworkSettings() + } + } + }.store(in: &cancellables) + } + private func loadProviderConfiguration() throws { guard configuration.loadSettingsFromProviderConfiguration else { return @@ -105,7 +127,7 @@ open class TransparentProxyProvider: NETransparentProxyProvider { return } - logger.log("Successfully Updated network settings: \(String(describing: error), privacy: .public))") + logger.log("Successfully Updated network settings: \(networkSettings.description, privacy: .public)") continuation.resume() } } @@ -116,35 +138,39 @@ open class TransparentProxyProvider: NETransparentProxyProvider { let networkSettings = NETransparentProxyNetworkSettings(tunnelRemoteAddress: "127.0.0.1") networkSettings.includedNetworkRules = [ - NENetworkRule(remoteNetwork: NWHostEndpoint(hostname: "127.0.0.1", port: ""), remotePrefix: 0, localNetwork: nil, localPrefix: 0, protocol: .any, direction: .outbound) + NENetworkRule(remoteNetwork: nil, remotePrefix: 0, localNetwork: nil, localPrefix: 0, protocol: .TCP, direction: .outbound), + NENetworkRule(remoteNetwork: nil, remotePrefix: 0, localNetwork: nil, localPrefix: 0, protocol: .UDP, direction: .outbound) ] + if isExcludedDomain("duckduckgo.com") { + networkSettings.includedNetworkRules?.append( + NENetworkRule(destinationHost: NWHostEndpoint(hostname: "duckduckgo.com", port: "443"), protocol: .any)) + } + return networkSettings } - override public func startProxy(options: [String: Any]?, - completionHandler: @escaping (Error?) -> Void) { + @MainActor + override open func startProxy(options: [String: Any]? = nil) async throws { eventHandler?(.startInitiated) - logger.log( - """ - Starting proxy\n - > configuration: \(String(describing: self.configuration), privacy: .public)\n - > settings: \(String(describing: self.settings), privacy: .public)\n - > options: \(String(describing: options), privacy: .public) - """) - do { - try loadProviderConfiguration() - } catch { - logger.error("Failed to load provider configuration, bailing out") - eventHandler?(.startFailure(error)) - completionHandler(error) - return - } + logger.log( + """ + Starting proxy\n + > configuration: \(String(describing: self.configuration), privacy: .public)\n + > settings: \(String(describing: self.settings), privacy: .public)\n + > options: \(String(describing: options), privacy: .public) + """) + + do { + try loadProviderConfiguration() + } catch { + logger.error("Failed to load provider configuration, bailing out") + throw error + } - Task { @MainActor in do { startMonitoringNetworkInterfaces() @@ -152,61 +178,82 @@ open class TransparentProxyProvider: NETransparentProxyProvider { logger.log("Proxy started successfully") isRunning = true eventHandler?(.startSuccess) - completionHandler(nil) } catch { let error = StartError.failedToUpdateNetworkSettings(underlyingError: error) logger.error("Proxy failed to start \(String(reflecting: error), privacy: .public)") - eventHandler?(.startFailure(error)) - completionHandler(error) + throw error } + } catch { + eventHandler?(.startFailure(error)) + throw error } } - override public func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { + @MainActor + open override func stopProxy(with reason: NEProviderStopReason) async { + logger.log("Stopping proxy with reason: \(String(reflecting: reason), privacy: .public)") - Task { @MainActor in - stopMonitoringNetworkInterfaces() - isRunning = false - completionHandler() - } + stopMonitoringNetworkInterfaces() + isRunning = false } + @MainActor override public func sleep(completionHandler: @escaping () -> Void) { - Task { @MainActor in - stopMonitoringNetworkInterfaces() - logger.log("The proxy is now sleeping") - completionHandler() - } + stopMonitoringNetworkInterfaces() + logger.log("The proxy is now sleeping") + completionHandler() } + @MainActor override public func wake() { - Task { @MainActor in - logger.log("The proxy is now awake") - startMonitoringNetworkInterfaces() - } + logger.log("The proxy is now awake") + startMonitoringNetworkInterfaces() + } + + private func logFlowMessage(_ flow: NEAppProxyFlow, level: OSLogType, message: String) { + logger.log( + level: level, + """ + \(message, privacy: .public) + - remote: \(String(reflecting: flow.remoteHostname), privacy: .public) + - flowID: \(String(reflecting: flow.metaData.filterFlowIdentifier?.uuidString), privacy: .public) + - appID: \(String(reflecting: flow.metaData.sourceAppSigningIdentifier), privacy: .public) + """ + ) + } + + private func logNewTCPFlow(_ flow: NEAppProxyFlow) { + logFlowMessage( + flow, + level: .default, + message: "[TCP] New flow: \(String(reflecting: flow))") + } + + private func logFlowHandlingFailure(_ flow: NEAppProxyFlow, message: String) { + logFlowMessage( + flow, + level: .error, + message: "[TCP] Failure handling flow: \(message)") } override public func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool { + logNewTCPFlow(flow) + guard let flow = flow as? NEAppProxyTCPFlow else { - logger.info("Expected a TCP flow, but got something else. We're ignoring it.") + logFlowHandlingFailure(flow, message: "Expected a TCP flow, but got something else. We're ignoring the flow.") return false } - guard let remoteEndpoint = flow.remoteEndpoint as? NWHostEndpoint, - !isDnsServer(remoteEndpoint) else { + guard let remoteEndpoint = flow.remoteEndpoint as? NWHostEndpoint else { + logFlowHandlingFailure(flow, message: "No remote endpoint. We're ignoring the flow.") return false } - let printableRemote = flow.remoteHostname ?? (flow.remoteEndpoint as? NWHostEndpoint)?.hostname ?? "unknown" - - logger.debug( - """ - [TCP] New flow: \(String(describing: flow), privacy: .public) - - remote: \(printableRemote, privacy: .public) - - flowID: \(String(describing: flow.metaData.filterFlowIdentifier?.uuidString), privacy: .public) - - appID: \(String(describing: flow.metaData.sourceAppSigningIdentifier), privacy: .public) - """) + guard !isDnsServer(remoteEndpoint) else { + logFlowHandlingFailure(flow, message: "DNS resolver endpoint. We're ignoring the flow.") + return false + } guard let interface else { logger.error("[TCP: \(String(describing: flow), privacy: .public)] Expected an interface to exclude traffic through") @@ -235,11 +282,13 @@ open class TransparentProxyProvider: NETransparentProxyProvider { flow.networkInterface = directInterface Task { @TCPFlowActor in - let flowManager = TCPFlowManager(flow: flow) + let flowManager = TCPFlowManager(flow: flow, logger: logger) tcpFlowManagers.insert(flowManager) try? await flowManager.start(interface: interface) tcpFlowManagers.remove(flowManager) + + logFlowMessage(flow, level: .default, message: "[TCP] Flow completed") } return true diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Animation/AnimationConstants.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Animation/AnimationConstants.swift new file mode 100644 index 00000000000..552e5dc433a --- /dev/null +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Animation/AnimationConstants.swift @@ -0,0 +1,23 @@ +// +// AnimationConstants.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +struct AnimationConstants { + static let highlightAnimationStepSpeed = 0.05 +} diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/StatusBarMenu.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/StatusBarMenu.swift index 9d541e976cb..53e2a245994 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/StatusBarMenu.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Menu/StatusBarMenu.swift @@ -37,7 +37,7 @@ public final class StatusBarMenu: NSObject { private let controller: TunnelController private let statusReporter: NetworkProtectionStatusReporter private let onboardingStatusPublisher: OnboardingStatusPublisher - private let uiActionHandler: VPNUIActionHandler + private let uiActionHandler: VPNUIActionHandling private let menuItems: () -> [MenuItem] private let agentLoginItem: LoginItem? private let isMenuBarStatusView: Bool @@ -64,7 +64,7 @@ public final class StatusBarMenu: NSObject { statusReporter: NetworkProtectionStatusReporter, controller: TunnelController, iconProvider: IconProvider, - uiActionHandler: VPNUIActionHandler, + uiActionHandler: VPNUIActionHandling, menuItems: @escaping () -> [MenuItem], agentLoginItem: LoginItem?, isMenuBarStatusView: Bool, @@ -108,7 +108,9 @@ public final class StatusBarMenu: NSObject { return } - togglePopover(isOptionKeyPressed: isOptionKeyPressed) + Task { @MainActor in + togglePopover(isOptionKeyPressed: isOptionKeyPressed) + } } private func subscribeToIconUpdates() { @@ -122,6 +124,7 @@ public final class StatusBarMenu: NSObject { // MARK: - Popover + @MainActor private func togglePopover(isOptionKeyPressed: Bool) { if let popover, popover.isShown { popover.close() @@ -131,19 +134,33 @@ public final class StatusBarMenu: NSObject { return } - popover = NetworkProtectionPopover(controller: controller, - onboardingStatusPublisher: onboardingStatusPublisher, - statusReporter: statusReporter, - uiActionHandler: uiActionHandler, - menuItems: menuItems, - agentLoginItem: agentLoginItem, - isMenuBarStatusView: isMenuBarStatusView, - userDefaults: userDefaults, - locationFormatter: locationFormatter, - uninstallHandler: uninstallHandler) + let siteTroubleshootingViewModel = SiteTroubleshootingView.Model( + featureFlagPublisher: Just(false).eraseToAnyPublisher(), + connectionStatusPublisher: Just(NetworkProtection.ConnectionStatus.disconnected).eraseToAnyPublisher(), + siteTroubleshootingInfoPublisher: Just(SiteTroubleshootingInfo?(nil)).eraseToAnyPublisher(), + uiActionHandler: uiActionHandler) + + let debugInformationViewModel = DebugInformationViewModel(showDebugInformation: isOptionKeyPressed) + + let statusViewModel = NetworkProtectionStatusView.Model( + controller: controller, + onboardingStatusPublisher: onboardingStatusPublisher, + statusReporter: statusReporter, + uiActionHandler: uiActionHandler, + menuItems: menuItems, + agentLoginItem: agentLoginItem, + isMenuBarStatusView: isMenuBarStatusView, + userDefaults: userDefaults, + locationFormatter: locationFormatter, + uninstallHandler: uninstallHandler) + + popover = NetworkProtectionPopover( + statusViewModel: statusViewModel, + statusReporter: statusReporter, + siteTroubleshootingViewModel: siteTroubleshootingViewModel, + debugInformationViewModel: debugInformationViewModel) popover?.behavior = .transient - popover?.setShowsDebugInformation(isOptionKeyPressed) popover?.show(relativeTo: button.bounds, of: button, preferredEdge: .minY) } } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionAsset.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionAsset.swift index a8288b7dbdc..e09c9c93a61 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionAsset.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionAsset.swift @@ -51,4 +51,7 @@ public enum NetworkProtectionAsset: String, CaseIterable { // Images: case allowSysexScreenshot = "allow-sysex-screenshot" case allowSysexScreenshotBigSur = "allow-sysex-screenshot-bigsur" + + // Accordion View + case accordionViewCheckmark = "Check-16D" } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift index 0d1837d6e89..a6ba7befa5f 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/NetworkProtectionPopover.swift @@ -45,34 +45,21 @@ public final class NetworkProtectionPopover: NSPopover { public typealias MenuItem = NetworkProtectionStatusView.Model.MenuItem - private let debugInformationPublisher = CurrentValueSubject(false) private let statusReporter: NetworkProtectionStatusReporter - private let model: NetworkProtectionStatusView.Model + private let debugInformationViewModel: DebugInformationViewModel + private let siteTroubleshootingViewModel: SiteTroubleshootingView.Model + private let statusViewModel: NetworkProtectionStatusView.Model private var appLifecycleCancellables = Set() - public required init(controller: TunnelController, - onboardingStatusPublisher: OnboardingStatusPublisher, + public required init(statusViewModel: NetworkProtectionStatusView.Model, statusReporter: NetworkProtectionStatusReporter, - uiActionHandler: VPNUIActionHandler, - menuItems: @escaping () -> [MenuItem], - agentLoginItem: LoginItem?, - isMenuBarStatusView: Bool, - userDefaults: UserDefaults, - locationFormatter: VPNLocationFormatting, - uninstallHandler: @escaping () async -> Void) { + siteTroubleshootingViewModel: SiteTroubleshootingView.Model, + debugInformationViewModel: DebugInformationViewModel) { self.statusReporter = statusReporter - self.model = NetworkProtectionStatusView.Model(controller: controller, - onboardingStatusPublisher: onboardingStatusPublisher, - statusReporter: statusReporter, - debugInformationPublisher: debugInformationPublisher.eraseToAnyPublisher(), - uiActionHandler: uiActionHandler, - menuItems: menuItems, - agentLoginItem: agentLoginItem, - isMenuBarStatusView: isMenuBarStatusView, - userDefaults: userDefaults, - locationFormatter: locationFormatter, - uninstallHandler: uninstallHandler) + self.debugInformationViewModel = debugInformationViewModel + self.siteTroubleshootingViewModel = siteTroubleshootingViewModel + self.statusViewModel = statusViewModel super.init() @@ -88,7 +75,11 @@ public final class NetworkProtectionPopover: NSPopover { } private func setupContentController() { - let view = NetworkProtectionStatusView(model: self.model).environment(\.dismiss, { [weak self] in + let view = NetworkProtectionStatusView() + .environmentObject(debugInformationViewModel) + .environmentObject(siteTroubleshootingViewModel) + .environmentObject(statusViewModel) + .environment(\.dismiss, { [weak self] in self?.close() }).fixedSize() @@ -106,7 +97,7 @@ public final class NetworkProtectionPopover: NSPopover { NotificationCenter .default .publisher(for: NSApplication.didBecomeActiveNotification) - .sink { [weak self] _ in self?.model.refreshLoginItemStatus() } + .sink { [weak self] _ in self?.statusViewModel.refreshLoginItemStatus() } .store(in: &appLifecycleCancellables) NotificationCenter @@ -117,20 +108,14 @@ public final class NetworkProtectionPopover: NSPopover { } private func closePopoverIfOnboarded() { - if self.model.onboardingStatus == .completed { + if self.statusViewModel.onboardingStatus == .completed { self.close() } } override public func show(relativeTo positioningRect: NSRect, of positioningView: NSView, preferredEdge: NSRectEdge) { statusReporter.forceRefresh() - model.refreshLoginItemStatus() + statusViewModel.refreshLoginItemStatus() super.show(relativeTo: positioningRect, of: positioningView, preferredEdge: preferredEdge) } - - // MARK: - Debug Information - - func setShowsDebugInformation(_ showsDebugInformation: Bool) { - debugInformationPublisher.send(showsDebugInformation) - } } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Check-16D.pdf b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Check-16D.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9a1b194b77f149b7545ffb923bd8fd91c59225a6 GIT binary patch literal 1525 zcmZux+iu%141L#E@TEZeP)C$RU4Wv%nqDw$!@6{D#U8vwO*16+7P~{YuP^C1mnIQ{ zSUx6scqox4_t&@QSOldIG}J$TDS(R$7~H(JcMomZ=G7Z^k8ugQh)(l@%gfbI*&V=5nD1*ZJ>koJV(8Fnrj38#n5Y8r&dE8-;~1Fo#}m&NsWw zH&bvPHX$$)6WIjgh1!@MZkln$pD9I61itWr$XO5<>mq7|z+}YYfXUDp6G@<;Q$T?n z8H$EIqhV_gW5r;ICWgcy1=QY%U35`vflzB7yg)rE6(MLFHM?%GO(JvktZYFm-N-H> zdF1p=ku)YpEE64BCY!UJc2?+gktinZz!t_^9l6@VpNt?b`D9&(aIDCzwg^^-*kc+E zTO~rDVi$=pCUAvL&a$8IY2w)8x1X0}i>A;PqnILB$7;4+2x_9^iV7Mc8s|YUV=<*} zM+P15u!zZV`hqb{NW@HxlJ@~wt|HRn=_+k3YE8c@4h*`<-EMUruume94npc~!r{Bj1be zM((sC`ZcuOts{+cQ@vw_l!l;I^5q{qktJZbU&vLF z1w2^#6*x~>TPOwAvj?TH2O)<2Sll?z>|CzJz25-4+J2_~zRVODmUvJ+4uv17W literal 0 HcmV?d00001 diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Contents.json b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Contents.json new file mode 100644 index 00000000000..20caa8ff8a7 --- /dev/null +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Resources/Assets.xcassets/Icons/Check-16D.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Check-16D.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" + } +} diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/AccordionView.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/AccordionView.swift new file mode 100644 index 00000000000..eb1cd4ce8e3 --- /dev/null +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/AccordionView.swift @@ -0,0 +1,119 @@ +// +// AccordionView.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import SwiftUI + +struct SideMenuStyle: MenuStyle { + func makeBody(configuration: Configuration) -> some View { + Menu(configuration) + .menuStyle(DefaultMenuStyle()) + .frame(maxWidth: .infinity, alignment: .leading) // Align the menu to the leading edge + } +} + +struct AccordionView: View { + @Environment(\.colorScheme) private var colorScheme + private var label: (Bool) -> Label + private let submenu: () -> Submenu + + private var highlightAnimationStepSpeed = AnimationConstants.highlightAnimationStepSpeed + + @State private var isHovered = false + @State private var highlightOverride: Bool? + @State private var showSubmenu = false + + private var isHighlighted: Bool { + highlightOverride ?? isHovered + } + + init(@ViewBuilder label: @escaping (Bool) -> Label, + @ViewBuilder submenu: @escaping () -> Submenu) { + + self.label = label + self.submenu = submenu + } + + var body: some View { + content + .frame(maxWidth: .infinity, alignment: .leading) + .contentShape(Rectangle()) + .cornerRadius(4) + } + + private func buttonBackground(highlighted: Bool) -> some View { + if highlighted { + return AnyView( + VisualEffectView(material: .selection, blendingMode: .withinWindow, state: .active, isEmphasized: true)) + } else { + return AnyView(Color.clear) + } + } + + private var content: some View { + VStack { + Button(action: { + buttonTapped() + }) { + HStack { + label(isHovered) + Spacer() + + if showSubmenu { + Image(systemName: "chevron.down") // Chevron pointing right + .foregroundColor(.gray) + } else { + Image(systemName: "chevron.right") // Chevron pointing right + .foregroundColor(.gray) + } + }.padding([.top, .bottom], 3) + .padding([.leading, .trailing], 9) + }.buttonStyle(PlainButtonStyle()) + .frame(maxWidth: .infinity, alignment: .leading) + .background( + buttonBackground(highlighted: isHighlighted) + ) + .onTapGesture { + buttonTapped() + } + .onHover { hovering in + isHovered = hovering + } + + if showSubmenu { + VStack { + submenu() + .frame(maxWidth: .infinity, alignment: .leading) + } + } + } + } + + private func buttonTapped() { + highlightOverride = false + + DispatchQueue.main.asyncAfter(deadline: .now() + highlightAnimationStepSpeed) { + highlightOverride = true + + DispatchQueue.main.asyncAfter(deadline: .now() + highlightAnimationStepSpeed) { + highlightOverride = nil + showSubmenu.toggle() + } + } + } +} diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemButton.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemButton.swift index 59e814b53c9..e8270c4a9fa 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemButton.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemButton.swift @@ -27,7 +27,7 @@ struct MenuItemButton: View { private let textColor: Color private let action: () async -> Void - private let highlightAnimationStepSpeed = 0.05 + private let highlightAnimationStepSpeed = AnimationConstants.highlightAnimationStepSpeed @State private var isHovered = false @State private var animatingTap = false diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemCustomButton.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemCustomButton.swift index cdd8bd79c87..dbef97ab235 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemCustomButton.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/SwiftUI/MenuItemCustomButton.swift @@ -24,7 +24,7 @@ struct MenuItemCustomButton: View { private var label: (Bool) -> Label private let action: () async -> Void - private let highlightAnimationStepSpeed = 0.05 + private let highlightAnimationStepSpeed = AnimationConstants.highlightAnimationStepSpeed @State private var isHovered = false @State private var animatingTap = false diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandler/VPNUIActionHandler.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandling/VPNUIActionHandling.swift similarity index 84% rename from LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandler/VPNUIActionHandler.swift rename to LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandling/VPNUIActionHandling.swift index 76ff99d563c..b57f8bcc555 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandler/VPNUIActionHandler.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/VPNUIActionHandling/VPNUIActionHandling.swift @@ -1,5 +1,5 @@ // -// VPNUIActionHandler.swift +// VPNUIActionHandling.swift // // Copyright © 2024 DuckDuckGo. All rights reserved. // @@ -18,8 +18,9 @@ import Foundation -public protocol VPNUIActionHandler { +public protocol VPNUIActionHandling { func moveAppToApplications() async + func setExclusion(_ exclude: Bool, forDomain domain: String) async func shareFeedback() async func showPrivacyPro() async func showVPNLocations() async diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationView.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationView.swift index 34ea0bb2b17..82c30728d49 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationView.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationView.swift @@ -31,25 +31,21 @@ public struct DebugInformationView: View { /// The view model that this instance will use. /// - @ObservedObject var model: DebugInformationViewModel - - // MARK: - Initializers - - public init(model: DebugInformationViewModel) { - self.model = model - } + @EnvironmentObject var model: DebugInformationViewModel // MARK: - View Contents public var body: some View { - Group { - VStack(alignment: .leading, spacing: 0) { - informationRow(title: "Bundle Path", details: model.bundlePath) - informationRow(title: "Version", details: model.version) + if model.showDebugInformation { + Group { + VStack(alignment: .leading, spacing: 0) { + informationRow(title: "Bundle Path", details: model.bundlePath) + informationRow(title: "Version", details: model.version) + } + + Divider() + .padding(EdgeInsets(top: 5, leading: 9, bottom: 5, trailing: 9)) } - - Divider() - .padding(EdgeInsets(top: 5, leading: 9, bottom: 5, trailing: 9)) } } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationViewModel.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationViewModel.swift index f8433a1c28d..d8186a65c72 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationViewModel.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/DebugInformationView/DebugInformationViewModel.swift @@ -21,15 +21,19 @@ import Foundation import NetworkProtection import SwiftUI -@MainActor public final class DebugInformationViewModel: ObservableObject { - var bundlePath: String - var version: String + let showDebugInformation: Bool + let bundlePath: String + let version: String + private var cancellables = Set() // MARK: - Initialization & Deinitialization - public init(bundle: Bundle = .main) { + public init(showDebugInformation: Bool, + bundle: Bundle = .main) { + + self.showDebugInformation = showDebugInformation bundlePath = bundle.bundlePath // swiftlint:disable:next force_cast diff --git a/LocalPackages/NetworkProtectionMac/Sources/VPNAppLauncher/AppLauncher+VPNUIActionHandler.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingInfo.swift similarity index 50% rename from LocalPackages/NetworkProtectionMac/Sources/VPNAppLauncher/AppLauncher+VPNUIActionHandler.swift rename to LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingInfo.swift index ed491f743b2..704cb2731e7 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/VPNAppLauncher/AppLauncher+VPNUIActionHandler.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingInfo.swift @@ -1,5 +1,5 @@ // -// AppLauncher+VPNUIActionHandler.swift +// SiteTroubleshootingInfo.swift // // Copyright © 2024 DuckDuckGo. All rights reserved. // @@ -16,25 +16,21 @@ // limitations under the License. // -import AppLauncher +import AppKit import Foundation -import NetworkProtectionUI -extension AppLauncher: VPNUIActionHandler { +public struct SiteTroubleshootingInfo { + public let icon: NSImage + public let domain: String + public let excluded: Bool - public func moveAppToApplications() async { - try? await launchApp(withCommand: VPNAppLaunchCommand.moveAppToApplications) + public init(icon: NSImage?, domain: String, excluded: Bool) { + self.icon = icon ?? NSImage(systemSymbolName: "globe", accessibilityDescription: nil)! + self.domain = domain + self.excluded = excluded } +} - public func shareFeedback() async { - try? await launchApp(withCommand: VPNAppLaunchCommand.shareFeedback) - } +extension SiteTroubleshootingInfo: Equatable { - public func showVPNLocations() async { - try? await launchApp(withCommand: VPNAppLaunchCommand.showVPNLocations) - } - - public func showPrivacyPro() async { - try? await launchApp(withCommand: VPNAppLaunchCommand.showPrivacyPro) - } } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingView.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingView.swift new file mode 100644 index 00000000000..ed7580369ba --- /dev/null +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingView.swift @@ -0,0 +1,97 @@ +// +// SiteTroubleshootingView.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine +import Foundation +import SwiftUI + +fileprivate extension View { + func applyCurrentSiteAttributes() -> some View { + font(.system(size: 13, weight: .regular, design: .default)) + } +} + +public struct SiteTroubleshootingView: View { + + @EnvironmentObject var model: Model + + // MARK: - View Contents + + public var body: some View { + if model.isFeatureEnabled, + let siteInfo = model.siteInfo { + siteTroubleshootingView(siteInfo) + } else { + EmptyView() + } + } + + private func siteTroubleshootingView(_ siteInfo: SiteTroubleshootingInfo) -> some View { + Group { + AccordionView { _ in + Image(nsImage: siteInfo.icon) + .resizable() + .frame(width: 16, height: 16) + .clipShape(RoundedRectangle(cornerRadius: 3.0)) + Text("\(siteInfo.domain) issues?") + .applyCurrentSiteAttributes() + } submenu: { + VStack { + MenuItemCustomButton { + model.setExclusion(true, forDomain: siteInfo.domain) + } label: { _ in + HStack { + if siteInfo.excluded { + Image(.accordionViewCheckmark) + .resizable() + .font(.system(size: 13)) + .frame(width: 16, height: 16) + .applyCurrentSiteAttributes() + } else { + Rectangle() + .fill(Color.clear) + .frame(width: 16, height: 16) + } + Text("Exclude from VPN") + } + } + + MenuItemCustomButton { + model.setExclusion(false, forDomain: siteInfo.domain) + } label: { _ in + if !siteInfo.excluded { + Image(.accordionViewCheckmark) + .resizable() + .font(.system(size: 13)) + .frame(width: 16, height: 16) + } else { + Rectangle() + .fill(Color.clear) + .frame(width: 16, height: 16) + } + + Text("Route through VPN") + } + } + } + + Divider() + .padding(EdgeInsets(top: 5, leading: 9, bottom: 5, trailing: 9)) + } + } +} diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingViewModel.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingViewModel.swift new file mode 100644 index 00000000000..b026feed85c --- /dev/null +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/SiteTroubleshootingView/SiteTroubleshootingViewModel.swift @@ -0,0 +1,88 @@ +// +// SiteTroubleshootingViewModel.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Combine +import Foundation +import NetworkProtection + +extension SiteTroubleshootingView { + + public final class Model: ObservableObject { + + @Published + private(set) var isFeatureEnabled = false + + @Published + private(set) var connectionStatus: ConnectionStatus = .disconnected + + @Published + private var internalSiteInfo: SiteTroubleshootingInfo? + + var siteInfo: SiteTroubleshootingInfo? { + guard case .connected = connectionStatus else { + return nil + } + + return internalSiteInfo + } + + private let uiActionHandler: VPNUIActionHandling + private var cancellables = Set() + + public init(featureFlagPublisher: AnyPublisher, + connectionStatusPublisher: AnyPublisher, + siteTroubleshootingInfoPublisher: AnyPublisher, + uiActionHandler: VPNUIActionHandling) { + + self.uiActionHandler = uiActionHandler + + subscribeToConnectionStatusChanges(connectionStatusPublisher) + subscribeToSiteTroubleshootingInfoChanges(siteTroubleshootingInfoPublisher) + subscribeToFeatureFlagChanges(featureFlagPublisher) + } + + private func subscribeToConnectionStatusChanges(_ publisher: AnyPublisher) { + + publisher + .receive(on: DispatchQueue.main) + .assign(to: \.connectionStatus, onWeaklyHeld: self) + .store(in: &cancellables) + } + + private func subscribeToSiteTroubleshootingInfoChanges(_ publisher: AnyPublisher) { + + publisher + .receive(on: DispatchQueue.main) + .assign(to: \.internalSiteInfo, onWeaklyHeld: self) + .store(in: &cancellables) + } + + private func subscribeToFeatureFlagChanges(_ publisher: AnyPublisher) { + publisher + .receive(on: DispatchQueue.main) + .assign(to: \.isFeatureEnabled, onWeaklyHeld: self) + .store(in: &cancellables) + } + + func setExclusion(_ exclude: Bool, forDomain domain: String) { + Task { @MainActor in + await uiActionHandler.setExclusion(exclude, forDomain: domain) + } + } + } +} diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift index 39a63eec043..22562a36ddc 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusView.swift @@ -38,13 +38,7 @@ public struct NetworkProtectionStatusView: View { /// The view model that this instance will use. /// - @ObservedObject var model: Model - - // MARK: - Initializers - - public init(model: Model) { - self.model = model - } + @EnvironmentObject var model: Model // MARK: - View Contents @@ -74,10 +68,8 @@ public struct NetworkProtectionStatusView: View { TunnelControllerView(model: model.tunnelControllerViewModel) .disabled(model.tunnelControllerViewDisabled) - if model.showDebugInformation { - DebugInformationView(model: DebugInformationViewModel()) - .transition(.slide) - } + DebugInformationView() + .transition(.slide) bottomMenuView() } diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift index 8c126a81422..835078e15bc 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/StatusView/NetworkProtectionStatusViewModel.swift @@ -73,15 +73,6 @@ extension NetworkProtectionStatusView { /// private let statusReporter: NetworkProtectionStatusReporter - /// The debug information publisher - /// - private let debugInformationPublisher: AnyPublisher - - /// Whether we're showing debug information - /// - @Published - var showDebugInformation: Bool - public let agentLoginItem: LoginItem? private let isMenuBarStatusView: Bool @@ -95,7 +86,7 @@ extension NetworkProtectionStatusView { /// private let runLoopMode: RunLoop.Mode? - private let uiActionHandler: VPNUIActionHandler + private let uiActionHandler: VPNUIActionHandling private let uninstallHandler: () async -> Void @@ -114,8 +105,7 @@ extension NetworkProtectionStatusView { public init(controller: TunnelController, onboardingStatusPublisher: OnboardingStatusPublisher, statusReporter: NetworkProtectionStatusReporter, - debugInformationPublisher: AnyPublisher, - uiActionHandler: VPNUIActionHandler, + uiActionHandler: VPNUIActionHandling, menuItems: @escaping () -> [MenuItem], agentLoginItem: LoginItem?, isMenuBarStatusView: Bool, @@ -127,7 +117,6 @@ extension NetworkProtectionStatusView { self.tunnelController = controller self.onboardingStatusPublisher = onboardingStatusPublisher self.statusReporter = statusReporter - self.debugInformationPublisher = debugInformationPublisher self.menuItems = menuItems self.agentLoginItem = agentLoginItem self.isMenuBarStatusView = isMenuBarStatusView @@ -147,7 +136,6 @@ extension NetworkProtectionStatusView { lastTunnelErrorMessage = statusReporter.connectionErrorObserver.recentValue lastControllerErrorMessage = statusReporter.controllerErrorMessageObserver.recentValue knownFailure = statusReporter.knownFailureObserver.recentValue - showDebugInformation = false // Particularly useful when unit testing with an initial status of our choosing. subscribeToStatusChanges() @@ -155,7 +143,6 @@ extension NetworkProtectionStatusView { subscribeToTunnelErrorMessages() subscribeToControllerErrorMessages() subscribeToKnownFailures() - subscribeToDebugInformationChanges() refreshLoginItemStatus() onboardingStatusPublisher @@ -255,14 +242,6 @@ extension NetworkProtectionStatusView { .store(in: &cancellables) } - private func subscribeToDebugInformationChanges() { - debugInformationPublisher - .removeDuplicates() - .receive(on: DispatchQueue.main) - .assign(to: \.showDebugInformation, onWeaklyHeld: self) - .store(in: &cancellables) - } - // MARK: - Connection Status: Errors @Published diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerView.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerView.swift index 3ef0d01d82f..96b5cab49ec 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerView.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerView.swift @@ -32,6 +32,10 @@ fileprivate extension Font { .system(size: 13, weight: .regular, design: .default) } + static var currentSite: Font { + .system(size: 13, weight: .regular, design: .default) + } + static var location: Font { .system(size: 13, weight: .regular, design: .default) } @@ -102,6 +106,10 @@ fileprivate extension View { .foregroundColor(Color(.defaultText)) } + func applyCurrentSiteAttributes() -> some View { + font(.NetworkProtection.currentSite) + } + func applyLocationAttributes() -> some View { font(.NetworkProtection.location) } @@ -172,6 +180,8 @@ public struct TunnelControllerView: View { Divider() .padding(EdgeInsets(top: 5, leading: 9, bottom: 5, trailing: 9)) + SiteTroubleshootingView() + locationView() if model.showServerDetails { diff --git a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerViewModel.swift b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerViewModel.swift index 08cc7614e78..19d4dd5ee78 100644 --- a/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerViewModel.swift +++ b/LocalPackages/NetworkProtectionMac/Sources/NetworkProtectionUI/Views/TunnelControllerView/TunnelControllerViewModel.swift @@ -57,7 +57,6 @@ public final class TunnelControllerViewModel: ObservableObject { private let statusReporter: NetworkProtectionStatusReporter private let vpnSettings: VPNSettings - private let locationFormatter: VPNLocationFormatting private static let byteCountFormatter: ByteCountFormatter = { @@ -67,7 +66,12 @@ public final class TunnelControllerViewModel: ObservableObject { return formatter }() - private let uiActionHandler: VPNUIActionHandler + private let uiActionHandler: VPNUIActionHandling + + // MARK: - Environment + + @EnvironmentObject + private var siteTroubleshootingViewModel: SiteTroubleshootingView.Model // MARK: - Misc @@ -91,7 +95,7 @@ public final class TunnelControllerViewModel: ObservableObject { runLoopMode: RunLoop.Mode? = nil, vpnSettings: VPNSettings, locationFormatter: VPNLocationFormatting, - uiActionHandler: VPNUIActionHandler) { + uiActionHandler: VPNUIActionHandling) { self.tunnelController = controller self.onboardingStatusPublisher = onboardingStatusPublisher @@ -531,11 +535,13 @@ public final class TunnelControllerViewModel: ObservableObject { } } +#if !APPSTORE && !DEBUG func moveToApplications() { Task { @MainActor in await uiActionHandler.moveAppToApplications() } } +#endif } extension DataVolume { diff --git a/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/MockVPNUIActionHandler/MockVPNUIActionHandler.swift b/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/MockVPNUIActionHandler/MockVPNUIActionHandler.swift index 5e0240ca3db..c8d60cf9ede 100644 --- a/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/MockVPNUIActionHandler/MockVPNUIActionHandler.swift +++ b/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/MockVPNUIActionHandler/MockVPNUIActionHandler.swift @@ -19,7 +19,10 @@ import Foundation import NetworkProtectionUI -public final class MockVPNUIActionHandler: VPNUIActionHandler { +public final class MockVPNUIActionHandler: VPNUIActionHandling { + public func setExclusion(_ exclude: Bool, forDomain domain: String) async { + // placeholder + } public func moveAppToApplications() async { // placeholder diff --git a/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionAssetTests.swift b/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionAssetTests.swift index b49d24d5b4e..345050aba41 100644 --- a/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionAssetTests.swift +++ b/LocalPackages/NetworkProtectionMac/Tests/NetworkProtectionUITests/NetworkProtectionAssetTests.swift @@ -49,7 +49,8 @@ final class NetworkProtectionAssetTests: XCTestCase { .statusbarBrandedVPNOffIcon: "statusbar-branded-vpn-off", .statusbarBrandedVPNIssueIcon: "statusbar-branded-vpn-issue", .allowSysexScreenshot: "allow-sysex-screenshot", - .allowSysexScreenshotBigSur: "allow-sysex-screenshot-bigsur" + .allowSysexScreenshotBigSur: "allow-sysex-screenshot-bigsur", + .accordionViewCheckmark: "Check-16D" ] XCTAssertEqual(assetsAndExpectedRawValues.count, NetworkProtectionAsset.allCases.count) diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index 6e9ed1cd74a..b725f60b577 100644 --- a/LocalPackages/SubscriptionUI/Package.swift +++ b/LocalPackages/SubscriptionUI/Package.swift @@ -12,7 +12,7 @@ let package = Package( targets: ["SubscriptionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "180.0.0-1"), .package(path: "../SwiftUIExtensions") ], targets: [ diff --git a/UnitTests/NavigationBar/View/NavigationBarPopoversTests.swift b/UnitTests/NavigationBar/View/NavigationBarPopoversTests.swift index d2982ee38ca..b1b050b5e81 100644 --- a/UnitTests/NavigationBar/View/NavigationBarPopoversTests.swift +++ b/UnitTests/NavigationBar/View/NavigationBarPopoversTests.swift @@ -27,6 +27,7 @@ final class NavigationBarPopoversTests: XCTestCase { private var sut: NavigationBarPopovers! private var autofillPopoverPresenter: MockAutofillPopoverPresenter! + @MainActor override func setUpWithError() throws { autofillPopoverPresenter = MockAutofillPopoverPresenter() sut = NavigationBarPopovers(networkProtectionPopoverManager: NetPPopoverManagerMock(), autofillPopoverPresenter: autofillPopoverPresenter) From 1a8aad71f8fa7de477762c9acbe54ab7f9ca0ed4 Mon Sep 17 00:00:00 2001 From: Sabrina Tardio <44158575+SabrinaTardio@users.noreply.github.com> Date: Wed, 7 Aug 2024 16:47:16 +0200 Subject: [PATCH 27/32] load Special special scripts immediately (#3081) Task/Issue URL: https://app.asana.com/0/1199230911884351/1207981214658241/f **Description**: Loads the Special Pages user scripts immediately without waiting for CBR rules loading --- DuckDuckGo.xcodeproj/project.pbxproj | 6 ++ .../xcshareddata/swiftpm/Package.resolved | 2 +- .../WKWebViewConfigurationExtensions.swift | 6 +- .../Experiment/PixelExperiment.swift | 4 +- .../SpecialPagesUserScriptExtension.swift | 71 +++++++++++++++++++ DuckDuckGo/Tab/Model/Tab.swift | 17 +++-- .../Tab/OnboardingPageTests.swift | 43 +++++++++++ UITests/OnboardingUITests.swift | 4 +- 8 files changed, 142 insertions(+), 11 deletions(-) create mode 100644 DuckDuckGo/Tab/Model/SpecialPagesUserScriptExtension.swift diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index 8d55d775a61..82a428455c0 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -1455,6 +1455,8 @@ 562532A12BC069190034D316 /* ZoomPopoverViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5625329D2BC069100034D316 /* ZoomPopoverViewModelTests.swift */; }; 562984702AC4610100AC20EB /* SyncPreferencesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5629846E2AC4610100AC20EB /* SyncPreferencesTests.swift */; }; 562984712AC469E400AC20EB /* SyncPreferencesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5629846E2AC4610100AC20EB /* SyncPreferencesTests.swift */; }; + 56406D4B2C636A8900BF8FA2 /* SpecialPagesUserScriptExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56406D4A2C636A8900BF8FA2 /* SpecialPagesUserScriptExtension.swift */; }; + 56406D4C2C636A8900BF8FA2 /* SpecialPagesUserScriptExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56406D4A2C636A8900BF8FA2 /* SpecialPagesUserScriptExtension.swift */; }; 56534DED29DF252C00121467 /* CapturingDefaultBrowserProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56534DEC29DF252C00121467 /* CapturingDefaultBrowserProvider.swift */; }; 56534DEE29DF252C00121467 /* CapturingDefaultBrowserProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56534DEC29DF252C00121467 /* CapturingDefaultBrowserProvider.swift */; }; 565E46E02B2725DD0013AC2A /* CriticalPathsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 565E46DF2B2725DD0013AC2A /* CriticalPathsTests.swift */; }; @@ -3468,6 +3470,7 @@ 561D66692B95C45A008ACC5C /* Suggestion.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Suggestion.storyboard; sourceTree = ""; }; 5625329D2BC069100034D316 /* ZoomPopoverViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZoomPopoverViewModelTests.swift; sourceTree = ""; }; 5629846E2AC4610100AC20EB /* SyncPreferencesTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncPreferencesTests.swift; sourceTree = ""; }; + 56406D4A2C636A8900BF8FA2 /* SpecialPagesUserScriptExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpecialPagesUserScriptExtension.swift; sourceTree = ""; }; 56534DEC29DF252C00121467 /* CapturingDefaultBrowserProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapturingDefaultBrowserProvider.swift; sourceTree = ""; }; 565E46DD2B2725DC0013AC2A /* SyncE2EUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SyncE2EUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 565E46DF2B2725DD0013AC2A /* CriticalPathsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CriticalPathsTests.swift; sourceTree = ""; }; @@ -7366,6 +7369,7 @@ 983DFB2428B67036006B7E34 /* UserContentUpdating.swift */, B634DBE2293C8FFF00C3C99E /* UserDialogRequest.swift */, 1D1A33482A6FEB170080ACED /* BurnerMode.swift */, + 56406D4A2C636A8900BF8FA2 /* SpecialPagesUserScriptExtension.swift */, ); path = Model; sourceTree = ""; @@ -10082,6 +10086,7 @@ 3706FB1A293F65D500E42796 /* OutlineSeparatorViewCell.swift in Sources */, 3706FB1B293F65D500E42796 /* SafariDataImporter.swift in Sources */, 3706FB1D293F65D500E42796 /* StatisticsLoader.swift in Sources */, + 56406D4C2C636A8900BF8FA2 /* SpecialPagesUserScriptExtension.swift in Sources */, 3793FDD829535EBA00A2E28F /* Assertions.swift in Sources */, F188267D2BBEB3AA00D9AC4F /* GeneralPixel.swift in Sources */, B62B48572ADE730D000DECE5 /* FileImportView.swift in Sources */, @@ -11411,6 +11416,7 @@ AAC30A28268E045400D2D9CD /* CrashReportReader.swift in Sources */, 85AC3B3525DA82A600C7D2AA /* DataTaskProviding.swift in Sources */, EECE10E529DD77E60044D027 /* FeatureFlag.swift in Sources */, + 56406D4B2C636A8900BF8FA2 /* SpecialPagesUserScriptExtension.swift in Sources */, AA3D531727A1EEED00074EC1 /* FeedbackViewController.swift in Sources */, AAEF6BC8276A081C0024DCF4 /* FaviconSelector.swift in Sources */, 4B2E7D6326FF9D6500D2DB17 /* PrintingUserScript.swift in Sources */, diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 743c6b243be..8f3c473b254 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -75,7 +75,7 @@ { "identity" : "lottie-spm", "kind" : "remoteSourceControl", - "location" : "https://github.com/airbnb/lottie-spm", + "location" : "https://github.com/airbnb/lottie-spm.git", "state" : { "revision" : "1d29eccc24cc8b75bff9f6804155112c0ffc9605", "version" : "4.4.3" diff --git a/DuckDuckGo/Common/Extensions/WKWebViewConfigurationExtensions.swift b/DuckDuckGo/Common/Extensions/WKWebViewConfigurationExtensions.swift index b0f641d8424..eed0d7c745a 100644 --- a/DuckDuckGo/Common/Extensions/WKWebViewConfigurationExtensions.swift +++ b/DuckDuckGo/Common/Extensions/WKWebViewConfigurationExtensions.swift @@ -20,11 +20,12 @@ import BrowserServicesKit import Combine import Common import WebKit +import UserScript extension WKWebViewConfiguration { @MainActor - func applyStandardConfiguration(contentBlocking: some ContentBlockingProtocol, burnerMode: BurnerMode) { + func applyStandardConfiguration(contentBlocking: some ContentBlockingProtocol, burnerMode: BurnerMode, earlyAccessHandlers: [UserScript] = []) { if case .burner(let websiteDataStore) = burnerMode { self.websiteDataStore = websiteDataStore // Fire Window: disable audio/video item info reporting to macOS Control Center / Lock Screen @@ -53,7 +54,8 @@ extension WKWebViewConfiguration { } let userContentController = UserContentController(assetsPublisher: contentBlocking.contentBlockingAssetsPublisher, - privacyConfigurationManager: contentBlocking.privacyConfigurationManager) + privacyConfigurationManager: contentBlocking.privacyConfigurationManager, + earlyAccessHandlers: earlyAccessHandlers) self.userContentController = userContentController self.processPool.geolocationProvider = GeolocationProvider(processPool: self.processPool) diff --git a/DuckDuckGo/Statistics/Experiment/PixelExperiment.swift b/DuckDuckGo/Statistics/Experiment/PixelExperiment.swift index 58fdee2b3ae..04465aa90fb 100644 --- a/DuckDuckGo/Statistics/Experiment/PixelExperiment.swift +++ b/DuckDuckGo/Statistics/Experiment/PixelExperiment.swift @@ -60,8 +60,8 @@ enum PixelExperiment: String, CaseIterable { // These are the variants. Rename or add/remove them as needed. If you change the string value // remember to keep it clear for privacy triage. - case control -// case newOnboarding = "ob" + case control = "oa" + case newOnboarding = "ob" } // These functions contain the business logic for determining if the pixel should be fired or not. diff --git a/DuckDuckGo/Tab/Model/SpecialPagesUserScriptExtension.swift b/DuckDuckGo/Tab/Model/SpecialPagesUserScriptExtension.swift new file mode 100644 index 00000000000..1fddfc49f92 --- /dev/null +++ b/DuckDuckGo/Tab/Model/SpecialPagesUserScriptExtension.swift @@ -0,0 +1,71 @@ +// +// SpecialPagesUserScriptExtension.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import BrowserServicesKit + +extension SpecialPagesUserScript { + @MainActor + func withOnboarding() { + let onboardingManager = buildOnboardingActionsManager() + let onboardingScript = OnboardingUserScript(onboardingActionsManager: onboardingManager) + self.registerSubfeature(delegate: onboardingScript) + } + + func withDuckPlayerIfAvailable() { + var youtubePlayerUserScript: YoutubePlayerUserScript? + if DuckPlayer.shared.isAvailable { + youtubePlayerUserScript = YoutubePlayerUserScript() + } + if let youtubePlayerUserScript { + self.registerSubfeature(delegate: youtubePlayerUserScript) + } + } + + func withErrorPages() { + let sslErrorPageUserScript = SSLErrorPageUserScript() + self.registerSubfeature(delegate: sslErrorPageUserScript) + } + +#if SPARKLE + func withReleaseNotes() { + let releaseNotesUserScript = ReleaseNotesUserScript() + self.registerSubfeature(delegate: releaseNotesUserScript) + } +#endif + + @MainActor + func withAllSubfeatures() { + withOnboarding() + withErrorPages() + withDuckPlayerIfAvailable() +#if SPARKLE + withReleaseNotes() +#endif + } + + @MainActor + private func buildOnboardingActionsManager() -> OnboardingActionsManaging { + return OnboardingActionsManager( + navigationDelegate: WindowControllersManager.shared, + dockCustomization: DockCustomizer(), + defaultBrowserProvider: SystemDefaultBrowserProvider(), + appearancePreferences: AppearancePreferences.shared, + startupPreferences: StartupPreferences.shared) + } +} diff --git a/DuckDuckGo/Tab/Model/Tab.swift b/DuckDuckGo/Tab/Model/Tab.swift index 7a1fd12d30b..66e1d4d423d 100644 --- a/DuckDuckGo/Tab/Model/Tab.swift +++ b/DuckDuckGo/Tab/Model/Tab.swift @@ -77,6 +77,7 @@ protocol NewWindowPolicyDecisionMaker { } private(set) var userContentController: UserContentController? + private(set) var specialPagesUserScript: SpecialPagesUserScript? @MainActor convenience init(content: TabContent, @@ -202,9 +203,14 @@ protocol NewWindowPolicyDecisionMaker { self.startupPreferences = startupPreferences self.tabsPreferences = tabsPreferences + self.specialPagesUserScript = SpecialPagesUserScript() + specialPagesUserScript? + .withAllSubfeatures() let configuration = webViewConfiguration ?? WKWebViewConfiguration() configuration.applyStandardConfiguration(contentBlocking: privacyFeatures.contentBlocking, - burnerMode: burnerMode) + burnerMode: burnerMode, + earlyAccessHandlers: specialPagesUserScript.map { [$0] } ?? []) + self.webViewConfiguration = configuration let userContentController = configuration.userContentController as? UserContentController assert(userContentController != nil) @@ -727,11 +733,11 @@ protocol NewWindowPolicyDecisionMaker { } #endif -// if PixelExperiment.cohort == .newOnboarding { -// setContent(.onboarding) -// } else { + if PixelExperiment.cohort == .newOnboarding { + setContent(.onboarding) + } else { setContent(.onboardingDeprecated) -// } + } } @MainActor(unsafe) @@ -1013,6 +1019,7 @@ extension Tab: UserContentControllerDelegate { userScripts.faviconScript.delegate = self userScripts.pageObserverScript.delegate = self userScripts.printingUserScript.delegate = self + specialPagesUserScript = nil } } diff --git a/IntegrationTests/Tab/OnboardingPageTests.swift b/IntegrationTests/Tab/OnboardingPageTests.swift index 54e8fd7fc9b..66a289cb317 100644 --- a/IntegrationTests/Tab/OnboardingPageTests.swift +++ b/IntegrationTests/Tab/OnboardingPageTests.swift @@ -37,6 +37,7 @@ final class OnboardingPageTests: XCTestCase { @MainActor override func setUp() { super.setUp() + _=WKUserContentController.swizzleScriptMessageHandlerWithReplyMethodsOnce webViewConfiguration = WKWebViewConfiguration() let contentBlockingMock = ContentBlockingMock() privacyFeaturesMock = AppPrivacyFeatures(contentBlocking: contentBlockingMock, httpsUpgradeStore: HTTPSUpgradeStoreMock()) @@ -50,6 +51,13 @@ final class OnboardingPageTests: XCTestCase { super.tearDown() } + @MainActor func testWhenTabInitialisedSpeacialPagesHandlersAdded() throws { + let tab = Tab(content: .onboarding) + let ucc = try XCTUnwrap(tab.userContentController) + + XCTAssertTrue(ucc.registeredScriptHandlerNames.contains("specialPages")) + } + @available(macOS 12.0, *) @MainActor func testWhenNavigatingToOnboarding_OnboardingPageIsPresented() async throws { // Given @@ -86,3 +94,38 @@ final class OnboardingPageTests: XCTestCase { } } + +extension WKUserContentController { + private static let scriptHandlersKey = UnsafeRawPointer(bitPattern: "scriptHandlersKey".hashValue)! + + private static var installedScriptHandlers: [(WKScriptMessageHandlerWithReply, WKContentWorld, String)] { + get { + objc_getAssociatedObject(self, scriptHandlersKey) as? [(WKScriptMessageHandlerWithReply, WKContentWorld, String)] ?? [] + } + set { + objc_setAssociatedObject(self, scriptHandlersKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } + + static let swizzleScriptMessageHandlerWithReplyMethodsOnce: Void = { + let originalAddMethod = class_getInstanceMethod(WKUserContentController.self, #selector(WKUserContentController.addScriptMessageHandler(_:contentWorld:name:)))! + let swizzledAddMethod = class_getInstanceMethod(WKUserContentController.self, #selector(swizzled_addScriptMessageHandler(_:contentWorld:name:)))! + method_exchangeImplementations(originalAddMethod, swizzledAddMethod) + }() + + @objc dynamic private func swizzled_addScriptMessageHandler(_ scriptMessageHandlerWithReply: WKScriptMessageHandlerWithReply, contentWorld: WKContentWorld, name: String) { + // Append the handler to our array + Self.installedScriptHandlers.append((scriptMessageHandlerWithReply, contentWorld, name)) + + // Call the original method + swizzled_addScriptMessageHandler(scriptMessageHandlerWithReply, contentWorld: contentWorld, name: name) + } + + var registeredScriptHandlerNames: [String] { + return Self.installedScriptHandlers.map { $0.2 } + } + + var registeredScriptHandlers: [(WKScriptMessageHandlerWithReply, WKContentWorld, String)] { + return Self.installedScriptHandlers + } +} diff --git a/UITests/OnboardingUITests.swift b/UITests/OnboardingUITests.swift index 669c4b9489e..d83b7515200 100644 --- a/UITests/OnboardingUITests.swift +++ b/UITests/OnboardingUITests.swift @@ -30,7 +30,9 @@ final class OnboardingUITests: XCTestCase { app.typeKey("n", modifierFlags: .command) let welcomeWindow = app.windows["Welcome"] - XCTAssertFalse(welcomeWindow.buttons["NavigationBarViewController.optionsButton"].isEnabled) + let optionsButton = welcomeWindow.buttons["NavigationBarViewController.optionsButton"] + XCTAssertTrue(optionsButton.waitForExistence(timeout: UITests.Timeouts.elementExistence)) + XCTAssertFalse(optionsButton.isEnabled) // Get Started XCTAssertTrue(welcomeWindow.webViews["Welcome"].staticTexts["Tired of being tracked online? We can help!"].waitForExistence(timeout: UITests.Timeouts.elementExistence)) From bdb16713022bd054784f52373c92fded446168b5 Mon Sep 17 00:00:00 2001 From: Marcos Gurgel Date: Wed, 7 Aug 2024 18:24:10 +0100 Subject: [PATCH 28/32] Bump BSK to 181.1.0 (sets Privacy Dashboard to 5.0.0) (#3050) --- DuckDuckGo.xcodeproj/project.pbxproj | 2 +- .../xcshareddata/swiftpm/Package.resolved | 8 ++++---- LocalPackages/DataBrokerProtection/Package.swift | 2 +- LocalPackages/NetworkProtectionMac/Package.swift | 2 +- LocalPackages/SubscriptionUI/Package.swift | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index db74e18d31d..a7d9a41cba1 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -13438,7 +13438,7 @@ repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit"; requirement = { kind = exactVersion; - version = 181.0.1; + version = 181.1.0; }; }; 9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = { diff --git a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index f3aa2641739..6f15f5f93c9 100644 --- a/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/DuckDuckGo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -32,8 +32,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/BrowserServicesKit", "state" : { - "revision" : "449b0dce6ea26e3d905ddd346b5498d28eebac3f", - "version" : "181.0.1" + "revision" : "ff87c19636bce8baa34b7984defa779c083f9ce9", + "version" : "181.1.0" } }, { @@ -104,8 +104,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/duckduckgo/privacy-dashboard", "state" : { - "revision" : "348594efe2cd40ef156e915c272d02ec22f1903f", - "version" : "4.2.0" + "revision" : "36dc07cba4bc1e7e0c1d1fb679c3cd077694a072", + "version" : "5.0.0" } }, { diff --git a/LocalPackages/DataBrokerProtection/Package.swift b/LocalPackages/DataBrokerProtection/Package.swift index 85b73363e49..2e711149510 100644 --- a/LocalPackages/DataBrokerProtection/Package.swift +++ b/LocalPackages/DataBrokerProtection/Package.swift @@ -29,7 +29,7 @@ let package = Package( targets: ["DataBrokerProtection"]) ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "181.0.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "181.1.0"), .package(path: "../SwiftUIExtensions"), .package(path: "../XPCHelper"), ], diff --git a/LocalPackages/NetworkProtectionMac/Package.swift b/LocalPackages/NetworkProtectionMac/Package.swift index f039aa9fc44..ff572863c52 100644 --- a/LocalPackages/NetworkProtectionMac/Package.swift +++ b/LocalPackages/NetworkProtectionMac/Package.swift @@ -32,7 +32,7 @@ let package = Package( .library(name: "VPNAppLauncher", targets: ["VPNAppLauncher"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "181.0.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "181.1.0"), .package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.3"), .package(path: "../AppLauncher"), .package(path: "../UDSHelper"), diff --git a/LocalPackages/SubscriptionUI/Package.swift b/LocalPackages/SubscriptionUI/Package.swift index 1ee2fae5ecc..55fe8064e1f 100644 --- a/LocalPackages/SubscriptionUI/Package.swift +++ b/LocalPackages/SubscriptionUI/Package.swift @@ -12,7 +12,7 @@ let package = Package( targets: ["SubscriptionUI"]), ], dependencies: [ - .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "181.0.1"), + .package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "181.1.0"), .package(path: "../SwiftUIExtensions") ], targets: [ From 0257003797ad9edbbbfa49e6a6cc0270174eab4d Mon Sep 17 00:00:00 2001 From: Brad Slayter Date: Wed, 7 Aug 2024 12:37:33 -0500 Subject: [PATCH 29/32] DBP waitlist removal (#3074) Task/Issue URL: https://app.asana.com/0/1203581873609357/1206988388191940 Tech Design URL: CC: **Description**: This PR removes all DBP waitlist references and pixels **Steps to test this PR**: 1. Smoke test DBP feature **Definition of Done**: * [ ] Does this PR satisfy our [Definition of Done](https://app.asana.com/0/1202500774821704/1207634633537039/f)? --- ###### Internal references: [Pull Request Review Checklist](https://app.asana.com/0/1202500774821704/1203764234894239/f) [Software Engineering Expectations](https://app.asana.com/0/59792373528535/199064865822552) [Technical Design Template](https://app.asana.com/0/59792373528535/184709971311943) [Pull Request Documentation](https://app.asana.com/0/1202500774821704/1204012835277482/f) --- .../App/DBP/DuckDuckGoDBPAgent.xcconfig | 2 +- .../DBP/DuckDuckGoDBPAgentAppStore.xcconfig | 2 +- Configuration/App/DuckDuckGo.xcconfig | 2 +- Configuration/Common.xcconfig | 2 +- Configuration/Tests/IntegrationTests.xcconfig | 2 +- Configuration/Tests/UnitTests.xcconfig | 2 +- .../Tests/UnitTestsAppStore.xcconfig | 2 +- DuckDuckGo.xcodeproj/project.pbxproj | 12 -- DuckDuckGo/Application/AppDelegate.swift | 10 -- DuckDuckGo/Application/URLEventHandler.swift | 7 - .../Common/Extensions/BundleExtension.swift | 4 - .../Common/Localizables/UserText+DBP.swift | 55 ------- DuckDuckGo/DBP/DBPHomeViewController.swift | 30 ---- .../DBP/DataBrokerProtectionAppEvents.swift | 38 ----- .../DBP/DataBrokerProtectionDebugMenu.swift | 46 ------ ...okerProtectionExternalWaitlistPixels.swift | 46 ------ .../DataBrokerProtectionFeatureDisabler.swift | 23 +-- ...ataBrokerProtectionFeatureGatekeeper.swift | 76 +-------- ...taBrokerProtectionLoginItemInterface.swift | 4 - .../DBP/DataBrokerProtectionManager.swift | 8 - ...erProtectionSubscriptionEventHandler.swift | 3 - .../DBP/LoginItem+DataBrokerProtection.swift | 4 - DuckDuckGo/Menus/MainMenu.swift | 3 - DuckDuckGo/Menus/MainMenuActions.swift | 8 - .../NavigationBar/View/MoreOptionsMenu.swift | 6 - .../View/NavigationBarViewController.swift | 2 - .../Tab/View/BrowserTabViewController.swift | 18 --- .../Storage/WaitlistActivationDateStore.swift | 5 - .../Waitlist/Views/WaitlistRootView.swift | 56 ------- .../WaitlistSteps/InvitedToWaitlistView.swift | 14 -- .../WaitlistSteps/JoinWaitlistView.swift | 14 -- .../WaitlistSteps/JoinedWaitlistView.swift | 15 -- .../WaitlistTermsAndConditionsView.swift | 131 --------------- .../WaitlistThankYouPromptPresenter.swift | 36 +---- .../Waitlist/Views/WaitlistThankYouView.swift | 7 - .../WaitlistViewControllerPresenter.swift | 47 ------ DuckDuckGo/Waitlist/Waitlist.swift | 84 ---------- .../WaitlistFeatureSetupHandler.swift | 12 -- ...tlistTermsAndConditionsActionHandler.swift | 21 --- .../View/WindowControllersManager.swift | 2 - .../DataBrokerProtectionPixelTests.swift | 149 ------------------ ...okerProtectionFeatureGatekeeperTests.swift | 89 ----------- 42 files changed, 18 insertions(+), 1081 deletions(-) delete mode 100644 DuckDuckGo/DBP/DataBrokerProtectionExternalWaitlistPixels.swift delete mode 100644 DuckDuckGo/Waitlist/Views/WaitlistRootView.swift delete mode 100644 LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionPixelTests.swift diff --git a/Configuration/App/DBP/DuckDuckGoDBPAgent.xcconfig b/Configuration/App/DBP/DuckDuckGoDBPAgent.xcconfig index edfa5572202..5a43ef574c9 100644 --- a/Configuration/App/DBP/DuckDuckGoDBPAgent.xcconfig +++ b/Configuration/App/DBP/DuckDuckGoDBPAgent.xcconfig @@ -47,7 +47,7 @@ PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*] = PROVISIONING_PROFILE_SPECIFIER[config=Review][sdk=macosx*] = macOS DBP Agent - Review PROVISIONING_PROFILE_SPECIFIER[config=Release][sdk=macosx*] = macOS DBP Agent - Release -FEATURE_FLAGS = FEEDBACK DBP +FEATURE_FLAGS = FEEDBACK GCC_PREPROCESSOR_DEFINITIONS[arch=*][sdk=*] = DBP=1 NETP_SYSTEM_EXTENSION=1 GCC_PREPROCESSOR_DEFINITIONS[config=CI][arch=*][sdk=*] = DBP=1 NETP_SYSTEM_EXTENSION=1 DEBUG=1 CI=1 $(inherited) diff --git a/Configuration/App/DBP/DuckDuckGoDBPAgentAppStore.xcconfig b/Configuration/App/DBP/DuckDuckGoDBPAgentAppStore.xcconfig index e19a23209a7..a38ea9f43e3 100644 --- a/Configuration/App/DBP/DuckDuckGoDBPAgentAppStore.xcconfig +++ b/Configuration/App/DBP/DuckDuckGoDBPAgentAppStore.xcconfig @@ -49,7 +49,7 @@ PROVISIONING_PROFILE_SPECIFIER[sdk=macosx*] = PROVISIONING_PROFILE_SPECIFIER[config=Review][sdk=macosx*] = match AppStore com.duckduckgo.mobile.ios.DBP.backgroundAgent.review macos PROVISIONING_PROFILE_SPECIFIER[config=Release][sdk=macosx*] = match AppStore com.duckduckgo.mobile.ios.DBP.backgroundAgent macos -FEATURE_FLAGS = FEEDBACK DBP +FEATURE_FLAGS = FEEDBACK GCC_PREPROCESSOR_DEFINITIONS[arch=*][sdk=*] = DBP=1 NETP_SYSTEM_EXTENSION=1 GCC_PREPROCESSOR_DEFINITIONS[config=CI][arch=*][sdk=*] = DBP=1 NETP_SYSTEM_EXTENSION=1 DEBUG=1 CI=1 $(inherited) diff --git a/Configuration/App/DuckDuckGo.xcconfig b/Configuration/App/DuckDuckGo.xcconfig index 8a851a43b1c..9747795f35b 100644 --- a/Configuration/App/DuckDuckGo.xcconfig +++ b/Configuration/App/DuckDuckGo.xcconfig @@ -26,7 +26,7 @@ CODE_SIGN_IDENTITY[sdk=macosx*] = Developer ID Application CODE_SIGN_IDENTITY[config=Debug][sdk=macosx*] = Apple Development CODE_SIGN_IDENTITY[config=CI][sdk=macosx*] = -FEATURE_FLAGS = FEEDBACK SPARKLE DBP STRIPE +FEATURE_FLAGS = FEEDBACK SPARKLE STRIPE PRODUCT_NAME_PREFIX = DuckDuckGo diff --git a/Configuration/Common.xcconfig b/Configuration/Common.xcconfig index 04c51ab42eb..e83abad09c2 100644 --- a/Configuration/Common.xcconfig +++ b/Configuration/Common.xcconfig @@ -21,7 +21,7 @@ COMBINE_HIDPI_IMAGES = YES DEVELOPMENT_TEAM = HKE973VLUW DEVELOPMENT_TEAM[config=CI][sdk=*] = -FEATURE_FLAGS = FEEDBACK DBP +FEATURE_FLAGS = FEEDBACK GCC_PREPROCESSOR_DEFINITIONS[config=CI][arch=*][sdk=*] = DEBUG=1 CI=1 $(inherited) GCC_PREPROCESSOR_DEFINITIONS[config=Debug][arch=*][sdk=*] = DEBUG=1 $(inherited) diff --git a/Configuration/Tests/IntegrationTests.xcconfig b/Configuration/Tests/IntegrationTests.xcconfig index 5d6620f67b8..128cc39a610 100644 --- a/Configuration/Tests/IntegrationTests.xcconfig +++ b/Configuration/Tests/IntegrationTests.xcconfig @@ -17,7 +17,7 @@ MACOSX_DEPLOYMENT_TARGET = 11.4 -FEATURE_FLAGS = FEEDBACK DBP +FEATURE_FLAGS = FEEDBACK INFOPLIST_FILE = IntegrationTests/Info.plist PRODUCT_BUNDLE_IDENTIFIER = com.duckduckgo.Integration-Tests diff --git a/Configuration/Tests/UnitTests.xcconfig b/Configuration/Tests/UnitTests.xcconfig index 7f159393138..24d10b6755d 100644 --- a/Configuration/Tests/UnitTests.xcconfig +++ b/Configuration/Tests/UnitTests.xcconfig @@ -17,7 +17,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -FEATURE_FLAGS = FEEDBACK DBP +FEATURE_FLAGS = FEEDBACK INFOPLIST_FILE = UnitTests/Info.plist PRODUCT_BUNDLE_IDENTIFIER = com.duckduckgo.macos.browser.DuckDuckGoTests diff --git a/Configuration/Tests/UnitTestsAppStore.xcconfig b/Configuration/Tests/UnitTestsAppStore.xcconfig index e1876243999..fb908433601 100644 --- a/Configuration/Tests/UnitTestsAppStore.xcconfig +++ b/Configuration/Tests/UnitTestsAppStore.xcconfig @@ -16,7 +16,7 @@ #include "UnitTests.xcconfig" #include "../AppStore.xcconfig" -FEATURE_FLAGS = FEEDBACK DBP +FEATURE_FLAGS = FEEDBACK PRODUCT_BUNDLE_IDENTIFIER = com.duckduckgo.mobile.ios.DuckDuckGoTests diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index a7d9a41cba1..69668943f26 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -1322,8 +1322,6 @@ 4B9DB0422A983B24000927DB /* WaitlistDialogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9DB0182A983B24000927DB /* WaitlistDialogView.swift */; }; 4B9DB0442A983B24000927DB /* WaitlistModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9DB0192A983B24000927DB /* WaitlistModalViewController.swift */; }; 4B9DB0452A983B24000927DB /* WaitlistModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9DB0192A983B24000927DB /* WaitlistModalViewController.swift */; }; - 4B9DB0472A983B24000927DB /* WaitlistRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9DB01A2A983B24000927DB /* WaitlistRootView.swift */; }; - 4B9DB0482A983B24000927DB /* WaitlistRootView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9DB01A2A983B24000927DB /* WaitlistRootView.swift */; }; 4B9DB04A2A983B24000927DB /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9DB01C2A983B24000927DB /* NotificationService.swift */; }; 4B9DB04B2A983B24000927DB /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9DB01C2A983B24000927DB /* NotificationService.swift */; }; 4B9DB0542A983B55000927DB /* MockWaitlistStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4B9DB04F2A983B55000927DB /* MockWaitlistStorage.swift */; }; @@ -2542,8 +2540,6 @@ BBB881892C4029BA001247C6 /* BookmarkListTreeControllerSearchDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBB881872C4029BA001247C6 /* BookmarkListTreeControllerSearchDataSource.swift */; }; BBBEE1BF2C4FF63600035ABA /* SortBookmarksViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBEE1BE2C4FF63600035ABA /* SortBookmarksViewModelTests.swift */; }; BBBEE1C02C4FF63600035ABA /* SortBookmarksViewModelTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBBEE1BE2C4FF63600035ABA /* SortBookmarksViewModelTests.swift */; }; - BBDFDC5A2B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBDFDC592B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift */; }; - BBDFDC5D2B2B8E2100F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBDFDC592B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift */; }; BBFB727F2C48047C0088884C /* SortBookmarksViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBFB727E2C48047C0088884C /* SortBookmarksViewModel.swift */; }; BBFB72802C48047C0088884C /* SortBookmarksViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBFB727E2C48047C0088884C /* SortBookmarksViewModel.swift */; }; BBFF355D2C4AF26200DA3289 /* BookmarksSortModeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = BBFF355C2C4AF26200DA3289 /* BookmarksSortModeTests.swift */; }; @@ -3382,7 +3378,6 @@ 4B9DB0172A983B24000927DB /* JoinWaitlistView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JoinWaitlistView.swift; sourceTree = ""; }; 4B9DB0182A983B24000927DB /* WaitlistDialogView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WaitlistDialogView.swift; sourceTree = ""; }; 4B9DB0192A983B24000927DB /* WaitlistModalViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WaitlistModalViewController.swift; sourceTree = ""; }; - 4B9DB01A2A983B24000927DB /* WaitlistRootView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WaitlistRootView.swift; sourceTree = ""; }; 4B9DB01C2A983B24000927DB /* NotificationService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; 4B9DB04F2A983B55000927DB /* MockWaitlistStorage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockWaitlistStorage.swift; sourceTree = ""; }; 4B9DB0502A983B55000927DB /* MockNotificationService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockNotificationService.swift; sourceTree = ""; }; @@ -4229,7 +4224,6 @@ BB7B5F972C4ED73800BA4AF8 /* BookmarksSearchAndSortMetrics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksSearchAndSortMetrics.swift; sourceTree = ""; }; BBB881872C4029BA001247C6 /* BookmarkListTreeControllerSearchDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarkListTreeControllerSearchDataSource.swift; sourceTree = ""; }; BBBEE1BE2C4FF63600035ABA /* SortBookmarksViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortBookmarksViewModelTests.swift; sourceTree = ""; }; - BBDFDC592B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataBrokerProtectionExternalWaitlistPixels.swift; sourceTree = ""; }; BBFB727E2C48047C0088884C /* SortBookmarksViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SortBookmarksViewModel.swift; sourceTree = ""; }; BBFF355C2C4AF26200DA3289 /* BookmarksSortModeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BookmarksSortModeTests.swift; sourceTree = ""; }; BD384AC72BBC821100EF3735 /* vpn-light-mode.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = "vpn-light-mode.json"; sourceTree = ""; }; @@ -4830,7 +4824,6 @@ 316913252BD2B76F0051B46D /* DataBrokerPrerequisitesStatusVerifier.swift */, 3199C6FC2AF97367002A7BA1 /* DataBrokerProtectionAppEvents.swift */, 316850712AF3AD58009A2828 /* DataBrokerProtectionDebugMenu.swift */, - BBDFDC592B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift */, 3199C6F82AF94F5B002A7BA1 /* DataBrokerProtectionFeatureDisabler.swift */, 31C5FFB82AF64D120008A79F /* DataBrokerProtectionFeatureGatekeeper.swift */, F1C70D782BFF50A400599292 /* DataBrokerProtectionLoginItemInterface.swift */, @@ -5771,7 +5764,6 @@ 4B9DB0182A983B24000927DB /* WaitlistDialogView.swift */, 4B9DB0192A983B24000927DB /* WaitlistModalViewController.swift */, 3168506C2AF3AD1C009A2828 /* WaitlistViewControllerPresenter.swift */, - 4B9DB01A2A983B24000927DB /* WaitlistRootView.swift */, 4B520F622BA5573A006405C7 /* WaitlistThankYouView.swift */, 4B6B64832BA930420009FF9F /* WaitlistThankYouPromptPresenter.swift */, ); @@ -10046,10 +10038,8 @@ 3706FAFD293F65D500E42796 /* DownloadsPopover.swift in Sources */, 3706FAFE293F65D500E42796 /* SpacerNode.swift in Sources */, 3706FB00293F65D500E42796 /* PasswordManagementCreditCardModel.swift in Sources */, - BBDFDC5D2B2B8E2100F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift in Sources */, 3706FB01293F65D500E42796 /* NSEventExtension.swift in Sources */, 3706FB02293F65D500E42796 /* Onboarding.swift in Sources */, - 4B9DB0482A983B24000927DB /* WaitlistRootView.swift in Sources */, 3706FEB8293F6EFB00E42796 /* ConnectBitwardenView.swift in Sources */, 1DFAB51E2A8982A600A0F7F6 /* SetExtension.swift in Sources */, B60C6F8E29B200AB007BFAA8 /* SavePanelAccessoryView.swift in Sources */, @@ -11511,7 +11501,6 @@ 9F6434612BEC82B700D2D8A0 /* AttributionPixelHandler.swift in Sources */, B684592225C93BE000DC17B6 /* Publisher.asVoid.swift in Sources */, 4B9DB01D2A983B24000927DB /* Waitlist.swift in Sources */, - BBDFDC5A2B2B8A0900F62D90 /* DataBrokerProtectionExternalWaitlistPixels.swift in Sources */, AAA0CC33252F181A0079BC96 /* NavigationButtonMenuDelegate.swift in Sources */, 1DA84D2F2C11989D0011C80F /* Update.swift in Sources */, AAC30A2A268E239100D2D9CD /* CrashReport.swift in Sources */, @@ -11910,7 +11899,6 @@ AA7EB6E527E7D6DC00036718 /* AnimationView.swift in Sources */, 8562599A269CA0A600EE44BC /* NSRectExtension.swift in Sources */, 4B37EE5F2B4CFC3C00A89A61 /* HomePageRemoteMessagingStorage.swift in Sources */, - 4B9DB0472A983B24000927DB /* WaitlistRootView.swift in Sources */, 31F28C5128C8EEC500119F70 /* YoutubeOverlayUserScript.swift in Sources */, B6ABD0CA2BC03F610000EB69 /* SecurityScopedFileURLController.swift in Sources */, B6040856274B830F00680351 /* DictionaryExtension.swift in Sources */, diff --git a/DuckDuckGo/Application/AppDelegate.swift b/DuckDuckGo/Application/AppDelegate.swift index 45cc31c17a0..0978ae7504d 100644 --- a/DuckDuckGo/Application/AppDelegate.swift +++ b/DuckDuckGo/Application/AppDelegate.swift @@ -106,7 +106,6 @@ final class AppDelegate: NSObject, NSApplicationDelegate { // MARK: - DBP -#if DBP private lazy var dataBrokerProtectionSubscriptionEventHandler: DataBrokerProtectionSubscriptionEventHandler = { let authManager = DataBrokerAuthenticationManagerBuilder.buildAuthenticationManager(subscriptionManager: subscriptionManager) return DataBrokerProtectionSubscriptionEventHandler(featureDisabler: DataBrokerProtectionFeatureDisabler(), @@ -114,8 +113,6 @@ final class AppDelegate: NSObject, NSApplicationDelegate { pixelHandler: DataBrokerProtectionPixelsHandler()) }() -#endif - private lazy var vpnRedditSessionWorkaround: VPNRedditSessionWorkaround = { let ipcClient = VPNControllerXPCClient.shared let statusReporter = DefaultNetworkProtectionStatusReporter( @@ -374,13 +371,8 @@ final class AppDelegate: NSObject, NSApplicationDelegate { NetworkProtectionAppEvents(featureGatekeeper: DefaultVPNFeatureGatekeeper(subscriptionManager: subscriptionManager)).applicationDidFinishLaunching() UNUserNotificationCenter.current().delegate = self -#if DBP dataBrokerProtectionSubscriptionEventHandler.registerForSubscriptionAccountManagerEvents() -#endif - -#if DBP DataBrokerProtectionAppEvents(featureGatekeeper: DefaultDataBrokerProtectionFeatureGatekeeper(accountManager: subscriptionManager.accountManager)).applicationDidFinishLaunching() -#endif setUpAutoClearHandler() @@ -427,11 +419,9 @@ final class AppDelegate: NSObject, NSApplicationDelegate { NetworkProtectionAppEvents(featureGatekeeper: DefaultVPNFeatureGatekeeper(subscriptionManager: subscriptionManager)).applicationDidBecomeActive() -#if DBP DataBrokerProtectionAppEvents(featureGatekeeper: DefaultDataBrokerProtectionFeatureGatekeeper(accountManager: subscriptionManager.accountManager)).applicationDidBecomeActive() -#endif subscriptionManager.refreshCachedSubscriptionAndEntitlements { isSubscriptionActive in if isSubscriptionActive { diff --git a/DuckDuckGo/Application/URLEventHandler.swift b/DuckDuckGo/Application/URLEventHandler.swift index 596737458a5..8e79662a1c3 100644 --- a/DuckDuckGo/Application/URLEventHandler.swift +++ b/DuckDuckGo/Application/URLEventHandler.swift @@ -23,10 +23,7 @@ import PixelKit import Subscription import NetworkProtectionUI import VPNAppLauncher - -#if DBP import DataBrokerProtection -#endif // @MainActor final class URLEventHandler { @@ -117,11 +114,9 @@ final class URLEventHandler { } } -#if DBP if url.scheme?.isDataBrokerProtectionScheme == true { handleDataBrokerProtectionURL(url) } -#endif DispatchQueue.main.async { if url.isFileURL && url.pathExtension == WebKitDownloadTask.downloadExtension { @@ -146,7 +141,6 @@ final class URLEventHandler { } } -#if DBP /// Handles DBP URLs /// private static func handleDataBrokerProtectionURL(_ url: URL) { @@ -160,7 +154,6 @@ final class URLEventHandler { return } } -#endif } private extension String { diff --git a/DuckDuckGo/Common/Extensions/BundleExtension.swift b/DuckDuckGo/Common/Extensions/BundleExtension.swift index 76fb870b32b..3ac81f66f5c 100644 --- a/DuckDuckGo/Common/Extensions/BundleExtension.swift +++ b/DuckDuckGo/Common/Extensions/BundleExtension.swift @@ -38,10 +38,8 @@ extension Bundle { static let ipcAppGroup = "IPC_APP_GROUP" -#if DBP static let dbpBackgroundAgentBundleId = "DBP_BACKGROUND_AGENT_BUNDLE_ID" static let dbpBackgroundAgentProductName = "DBP_BACKGROUND_AGENT_PRODUCT_NAME" -#endif } var buildNumber: String { @@ -87,7 +85,6 @@ extension Bundle { } #endif -#if DBP var dbpBackgroundAgentBundleId: String { guard let bundleID = object(forInfoDictionaryKey: Keys.dbpBackgroundAgentBundleId) as? String else { fatalError("Info.plist is missing \(Keys.dbpBackgroundAgentBundleId)") @@ -101,7 +98,6 @@ extension Bundle { } return loginItemsURL.appendingPathComponent(productName + ".app") } -#endif func appGroup(bundle: BundleGroup) -> String { let appGroupName = bundle.appGroupKey diff --git a/DuckDuckGo/Common/Localizables/UserText+DBP.swift b/DuckDuckGo/Common/Localizables/UserText+DBP.swift index 65590075e06..19ed7535b06 100644 --- a/DuckDuckGo/Common/Localizables/UserText+DBP.swift +++ b/DuckDuckGo/Common/Localizables/UserText+DBP.swift @@ -19,59 +19,6 @@ import Foundation import Common -#if DBP -// MARK: - Data Broker Protection Waitlist -extension UserText { - // "data-broker-protection.privacy-policy.title" - Privacy Policy title for Personal Information Removal - static let dataBrokerProtectionPrivacyPolicyTitle = "Privacy Policy" - // "data-broker-protection.waitlist.notification.title" - Title for Personal Information Removal waitlist notification - static let dataBrokerProtectionWaitlistNotificationTitle = "Personal Information Removal beta is ready!" - // "data-broker-protection.waitlist.notification.text" - Title for Personal Information Removal waitlist notification - static let dataBrokerProtectionWaitlistNotificationText = "Open your invite" - // "data-broker-protection.waitlist.join.title" - Title for Personal Information Removal join waitlist screen - static let dataBrokerProtectionWaitlistJoinTitle = "Personal Information Removal Beta" - // "data-broker-protection.waitlist.join.subtitle.1" - First subtitle for Personal Information Removal join waitlist screen - static let dataBrokerProtectionWaitlistJoinSubtitle1 = "Automatically scan and remove your data from 17+ sites that sell personal information with DuckDuckGo’s Personal Information Removal." - // "data-broker-protection.waitlist.joined.title" - Title for Personal Information Removal joined waitlist screen - static let dataBrokerProtectionWaitlistJoinedTitle = "You’re on the list!" - // "data-broker-protection.waitlist.joined.with-notifications.subtitle.1" - Subtitle 1 for Personal Information Removal joined waitlist screen when notifications are enabled - static let dataBrokerProtectionWaitlistJoinedWithNotificationsSubtitle1 = "New invites are sent every few days, on a first come, first served basis." - // "data-broker-protection.waitlist.joined.with-notifications.subtitle.2" - Subtitle 2 for Personal Information Removal joined waitlist screen when notifications are enabled - static let dataBrokerProtectionWaitlistJoinedWithNotificationsSubtitle2 = "We’ll notify you when your invite is ready." - // "data-broker-protection.waitlist.enable-notifications" - Enable notifications prompt for Personal Information Removal joined waitlist screen - static let dataBrokerProtectionWaitlistEnableNotifications = "Want to get a notification when your Personal Information Removal invite is ready?" - // "data-broker-protection.waitlist.invited.title" - Title for Personal Information Removal invited screen - static let dataBrokerProtectionWaitlistInvitedTitle = "You’re invited to try\nPersonal Information Removal beta!" - // "data-broker-protection.waitlist.invited.subtitle" - Subtitle for Personal Information Removal invited screen - static let dataBrokerProtectionWaitlistInvitedSubtitle = "Automatically find and remove your personal information – such as your name and address – from 17+ sites that store and sell it, reducing the risk of identity theft and spam." - // "data-broker-protection.waitlist.enable.title" - Title for Personal Information Removal enable screen - static let dataBrokerProtectionWaitlistEnableTitle = "Let’s get started" - // "data-broker-protection.waitlist.enable.subtitle" - Subtitle for Personal Information Removal enable screen - static let dataBrokerProtectionWaitlistEnableSubtitle = "We’ll need your name, address and the year you were born in order to find your personal information on data broker sites\n\nThis info is stored securely on your device, and is never sent to DuckDuckGo." - // "data-broker-protection.waitlist.availability-disclaimer" - Availability disclaimer for Personal Information Removal join waitlist screen - static let dataBrokerProtectionWaitlistAvailabilityDisclaimer = "Personal Information Removal is free during the beta.\nJoin the waitlist and we'll notify you when ready." - // "data-broker-protection.waitlist.button.close" - Close button for Personal Information Removal join waitlist screen - static let dataBrokerProtectionWaitlistButtonClose = "Close" - // "data-broker-protection.waitlist.button.done" - Close button for Personal Information Removal joined waitlist screen - static let dataBrokerProtectionWaitlistButtonDone = "Done" - // "data-broker-protection.waitlist.button.dismiss" - Dismiss button for Personal Information Removal join waitlist screen - static let dataBrokerProtectionWaitlistButtonDismiss = "Dismiss" - // "data-broker-protection.waitlist.button.cancel" - Cancel button for Personal Information Removal join waitlist screen - static let dataBrokerProtectionWaitlistButtonCancel = "Cancel" - // "data-broker-protection.waitlist.button.no-thanks" - No Thanks button for Personal Information Removal joined waitlist screen - static let dataBrokerProtectionWaitlistButtonNoThanks = "No Thanks" - // "data-broker-protection.waitlist.button.get-started" - Get Started button for Personal Information Removal joined waitlist screen - static let dataBrokerProtectionWaitlistButtonGetStarted = "Get Started" - // "data-broker-protection.waitlist.button.got-it" - Get started button for Personal Information Removal joined waitlist screen - static let dataBrokerProtectionWaitlistButtonGotIt = "Get started" - // "data-broker-protection.waitlist.button.enable-notifications" - Enable Notifications button for Personal Information Removal joined waitlist screen - static let dataBrokerProtectionWaitlistButtonEnableNotifications = "Enable Notifications" - // "data-broker-protection.waitlist.button.join-waitlist" - Join Waitlist button for Personal Information Removal join waitlist screen - static let dataBrokerProtectionWaitlistButtonJoinWaitlist = "Join the Waitlist" - // "data-broker-protection.waitlist.button.agree-and-continue" - Agree and Continue button for Personal Information Removal join waitlist screen - static let dataBrokerProtectionWaitlistButtonAgreeAndContinue = "Agree and Continue" -} - // MARK: - DBP Error pages extension UserText { static let dbpErrorPageBadPathTitle = NotLocalizedString("dbp.errorpage.bad.path.title", value: "Move DuckDuckGo App to Applications", comment: "Title for Personal Information Removal bad path error screen") @@ -82,5 +29,3 @@ extension UserText { static let dbpErrorPageNoPermissionMessage = NotLocalizedString("dbp.errorpage.no.permission.message", value: "Open System Settings and allow DuckDuckGo Personal Information Removal to run in the background.", comment: "Message for error screen when there is no permission") static let dbpErrorPageNoPermissionCTA = NotLocalizedString("dbp.errorpage.no.permission.cta", value: "Open System Settings...", comment: "Call to action for opening system settings") } - -#endif diff --git a/DuckDuckGo/DBP/DBPHomeViewController.swift b/DuckDuckGo/DBP/DBPHomeViewController.swift index 9f1848bcbed..6da4daef5e0 100644 --- a/DuckDuckGo/DBP/DBPHomeViewController.swift +++ b/DuckDuckGo/DBP/DBPHomeViewController.swift @@ -16,8 +16,6 @@ // limitations under the License. // -#if DBP - import Foundation import DataBrokerProtection import AppKit @@ -90,16 +88,6 @@ final class DBPHomeViewController: NSViewController { setupUI() setupObserver() - - do { - if try dataBrokerProtectionManager.dataManager.fetchProfile() != nil { - let dbpDateStore = DefaultWaitlistActivationDateStore(source: .dbp) - dbpDateStore.updateLastActiveDate() - } - } catch { - os_log("DBPHomeViewController error: viewDidLoad, error: %{public}@", log: .error, error.localizedDescription) - pixelHandler.fire(.generalError(error: error, functionOccurredIn: "DBPHomeViewController.viewDidLoad")) - } } override func viewDidAppear() { @@ -128,22 +116,6 @@ final class DBPHomeViewController: NSViewController { } } - private func presentInviteCodeFlow() { - let viewModel = DataBrokerProtectionInviteDialogsViewModel(delegate: self) - - let view = DataBrokerProtectionInviteDialogsView(viewModel: viewModel) - let hostingVC = NSHostingController(rootView: view) - presentedWindowController = hostingVC.wrappedInWindowController() - - guard let newWindow = presentedWindowController?.window, - let parentWindowController = WindowControllersManager.shared.lastKeyMainWindowController - else { - assertionFailure("Failed to present \(hostingVC)") - return - } - parentWindowController.window?.beginSheet(newWindow) - } - private func setupUIWithCurrentStatus() { setupUIWithStatus(prerequisiteVerifier.checkStatus()) } @@ -252,5 +224,3 @@ extension DBPHomeViewController { } } } - -#endif diff --git a/DuckDuckGo/DBP/DataBrokerProtectionAppEvents.swift b/DuckDuckGo/DBP/DataBrokerProtectionAppEvents.swift index 4c98934cc4a..4eeb776e441 100644 --- a/DuckDuckGo/DBP/DataBrokerProtectionAppEvents.swift +++ b/DuckDuckGo/DBP/DataBrokerProtectionAppEvents.swift @@ -16,8 +16,6 @@ // limitations under the License. // -#if DBP - import Foundation import LoginItems import Common @@ -46,15 +44,6 @@ struct DataBrokerProtectionAppEvents { } func applicationDidFinishLaunching() { - guard !featureGatekeeper.cleanUpDBPForPrivacyProIfNecessary() else { return } - - /// If the user is not in the waitlist and Privacy Pro flag is false, we want to remove the data for waitlist users - /// since the waitlist flag might have been turned off - if !featureGatekeeper.isFeatureVisible() && !featureGatekeeper.isPrivacyProEnabled() { - featureGatekeeper.disableAndDeleteForWaitlistUsers() - return - } - let loginItemsManager = LoginItemsManager() let loginItemInterface = DataBrokerProtectionManager.shared.loginItemInterface @@ -68,8 +57,6 @@ struct DataBrokerProtectionAppEvents { // Wait to make sure the agent has had time to restart before attempting to call a method on it try await Task.sleep(nanoseconds: 1_000_000_000) loginItemInterface.appLaunched() - } else { - featureGatekeeper.disableAndDeleteForWaitlistUsers() } } @@ -85,29 +72,6 @@ struct DataBrokerProtectionAppEvents { return } } - - guard !featureGatekeeper.cleanUpDBPForPrivacyProIfNecessary() else { return } - - /// If the user is not in the waitlist and Privacy Pro flag is false, we want to remove the data for waitlist users - /// since the waitlist flag might have been turned off - if !featureGatekeeper.isFeatureVisible() && !featureGatekeeper.isPrivacyProEnabled() { - featureGatekeeper.disableAndDeleteForWaitlistUsers() - return - } - } - - @MainActor - func handleWaitlistInvitedNotification(source: WaitlistNotificationSource) { - if DataBrokerProtectionWaitlist().readyToAcceptTermsAndConditions { - switch source { - case .cardUI: - DataBrokerProtectionExternalWaitlistPixels.fire(pixel: GeneralPixel.dataBrokerProtectionWaitlistCardUITapped, frequency: .dailyAndCount) - case .localPush: - DataBrokerProtectionExternalWaitlistPixels.fire(pixel: GeneralPixel.dataBrokerProtectionWaitlistNotificationTapped, frequency: .dailyAndCount) - } - - DataBrokerProtectionWaitlistViewControllerPresenter.show() - } } private func restartBackgroundAgent(loginItemsManager: LoginItemsManager) { @@ -118,5 +82,3 @@ struct DataBrokerProtectionAppEvents { // restartLoginItems doesn't work when we change the agent name } } - -#endif diff --git a/DuckDuckGo/DBP/DataBrokerProtectionDebugMenu.swift b/DuckDuckGo/DBP/DataBrokerProtectionDebugMenu.swift index a01fa5dc206..660cf055c58 100644 --- a/DuckDuckGo/DBP/DataBrokerProtectionDebugMenu.swift +++ b/DuckDuckGo/DBP/DataBrokerProtectionDebugMenu.swift @@ -16,8 +16,6 @@ // limitations under the License. // -#if DBP - import DataBrokerProtection import Foundation import AppKit @@ -56,25 +54,6 @@ final class DataBrokerProtectionDebugMenu: NSMenu { super.init(title: "Personal Information Removal") buildItems { - NSMenuItem(title: "Waitlist") { - NSMenuItem(title: "Reset Waitlist State", action: #selector(DataBrokerProtectionDebugMenu.resetWaitlistState)) - .targetting(self) - NSMenuItem(title: "Reset T&C Acceptance", action: #selector(DataBrokerProtectionDebugMenu.resetTermsAndConditionsAcceptance)) - .targetting(self) - - NSMenuItem(title: "Send Notification", action: #selector(DataBrokerProtectionDebugMenu.sendWaitlistAvailableNotification)) - .targetting(self) - - NSMenuItem.separator() - - NSMenuItem.separator() - - waitlistTokenItem - waitlistTimestampItem - waitlistInviteCodeItem - waitlistTermsAndConditionsAcceptedItem - } - NSMenuItem(title: "Environment") .submenu(environmentMenu) @@ -231,7 +210,6 @@ final class DataBrokerProtectionDebugMenu: NSMenu { @objc private func deleteAllDataAndStopAgent() { Task { @MainActor in guard case .alertFirstButtonReturn = await NSAlert.removeAllDBPStateAndDataAlert().runModal() else { return } - resetWaitlistState() DataBrokerProtectionFeatureDisabler().disableAndDelete() } } @@ -292,28 +270,6 @@ final class DataBrokerProtectionDebugMenu: NSMenu { } } - @objc private func resetWaitlistState() { - DataBrokerProtectionWaitlist().waitlistStorage.deleteWaitlistState() - KeychainAuthenticationData().reset() - - UserDefaults().removeObject(forKey: UserDefaultsWrapper.Key.shouldShowDBPWaitlistInvitedCardUI.rawValue) - UserDefaults().removeObject(forKey: UserDefaultsWrapper.Key.dataBrokerProtectionTermsAndConditionsAccepted.rawValue) - NotificationCenter.default.post(name: .dataBrokerProtectionWaitlistAccessChanged, object: nil) - os_log("DBP waitlist state cleaned", log: .dataBrokerProtection) - } - - @objc private func resetTermsAndConditionsAcceptance() { - UserDefaults().removeObject(forKey: UserDefaultsWrapper.Key.dataBrokerProtectionTermsAndConditionsAccepted.rawValue) - NotificationCenter.default.post(name: .dataBrokerProtectionWaitlistAccessChanged, object: nil) - os_log("DBP waitlist terms and conditions cleaned", log: .dataBrokerProtection) - } - - @objc private func sendWaitlistAvailableNotification() { - DataBrokerProtectionWaitlist().sendInviteCodeAvailableNotification(completion: nil) - - os_log("DBP waitlist notification sent", log: .dataBrokerProtection) - } - @objc private func toggleShowStatusMenuItem() { settings.showInMenuBar.toggle() } @@ -384,5 +340,3 @@ extension DataBrokerProtectionDebugMenu: NSWindowDelegate { dataBrokerForceOptOutWindowController = nil } } - -#endif diff --git a/DuckDuckGo/DBP/DataBrokerProtectionExternalWaitlistPixels.swift b/DuckDuckGo/DBP/DataBrokerProtectionExternalWaitlistPixels.swift deleted file mode 100644 index f23a4884a52..00000000000 --- a/DuckDuckGo/DBP/DataBrokerProtectionExternalWaitlistPixels.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// DataBrokerProtectionExternalWaitlistPixels.swift -// -// Copyright © 2023 DuckDuckGo. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation -import PixelKit - -struct DataBrokerProtectionExternalWaitlistPixels { - - static var isUserLocaleAllowed: Bool { - var regionCode: String? - if #available(macOS 13, *) { - regionCode = Locale.current.region?.identifier - } else { - regionCode = Locale.current.regionCode - } - -#if DEBUG // Always assume US for debug builds - regionCode = "US" -#endif - - return (regionCode ?? "US") == "US" - } - - static func fire(pixel: PixelKitEventV2, frequency: PixelKit.Frequency) { - if Self.isUserLocaleAllowed { - let isInternalUser = NSApp.delegateTyped.internalUserDecider.isInternalUser - let parameters = ["isInternalUser": isInternalUser.description] - PixelKit.fire(pixel, frequency: frequency, withAdditionalParameters: parameters) - } - } -} diff --git a/DuckDuckGo/DBP/DataBrokerProtectionFeatureDisabler.swift b/DuckDuckGo/DBP/DataBrokerProtectionFeatureDisabler.swift index 1e81a281e8e..66df5576110 100644 --- a/DuckDuckGo/DBP/DataBrokerProtectionFeatureDisabler.swift +++ b/DuckDuckGo/DBP/DataBrokerProtectionFeatureDisabler.swift @@ -16,8 +16,6 @@ // limitations under the License. // -#if DBP - import Foundation import DataBrokerProtection import Common @@ -41,19 +39,14 @@ struct DataBrokerProtectionFeatureDisabler: DataBrokerProtectionFeatureDisabling } func disableAndDelete() { - if !DefaultDataBrokerProtectionFeatureGatekeeper.bypassWaitlist { - - do { - try dataManager.removeAllData() - // the dataManagers delegate handles login item disabling - } catch { - os_log("DataBrokerProtectionFeatureDisabler error: disableAndDelete, error: %{public}@", log: .error, error.localizedDescription) - } - - DataBrokerProtectionLoginItemPixels.fire(pixel: GeneralPixel.dataBrokerDisableAndDeleteDaily, frequency: .daily) - NotificationCenter.default.post(name: .dbpWasDisabled, object: nil) + do { + try dataManager.removeAllData() + // the dataManagers delegate handles login item disabling + } catch { + os_log("DataBrokerProtectionFeatureDisabler error: disableAndDelete, error: %{public}@", log: .error, error.localizedDescription) } + + DataBrokerProtectionLoginItemPixels.fire(pixel: GeneralPixel.dataBrokerDisableAndDeleteDaily, frequency: .daily) + NotificationCenter.default.post(name: .dbpWasDisabled, object: nil) } } - -#endif diff --git a/DuckDuckGo/DBP/DataBrokerProtectionFeatureGatekeeper.swift b/DuckDuckGo/DBP/DataBrokerProtectionFeatureGatekeeper.swift index 8437d6962c3..491ca77a526 100644 --- a/DuckDuckGo/DBP/DataBrokerProtectionFeatureGatekeeper.swift +++ b/DuckDuckGo/DBP/DataBrokerProtectionFeatureGatekeeper.swift @@ -16,8 +16,6 @@ // limitations under the License. // -#if DBP - import Foundation import BrowserServicesKit import Common @@ -25,13 +23,9 @@ import DataBrokerProtection import Subscription protocol DataBrokerProtectionFeatureGatekeeper { - var waitlistIsOngoing: Bool { get } func isFeatureVisible() -> Bool func disableAndDeleteForAllUsers() - func disableAndDeleteForWaitlistUsers() func isPrivacyProEnabled() -> Bool - func isEligibleForThankYouMessage() -> Bool - func cleanUpDBPForPrivacyProIfNecessary() -> Bool func arePrerequisitesSatisfied() async -> Bool } @@ -40,35 +34,23 @@ struct DefaultDataBrokerProtectionFeatureGatekeeper: DataBrokerProtectionFeature private let featureDisabler: DataBrokerProtectionFeatureDisabling private let pixelHandler: EventMapping private let userDefaults: UserDefaults - private let waitlistStorage: WaitlistStorage private let subscriptionAvailability: SubscriptionFeatureAvailability private let accountManager: AccountManager - private let dataBrokerProtectionKey = "data-broker-protection.cleaned-up-from-waitlist-to-privacy-pro" - - /// Temporary code to use while we have both redeem flow for diary study users. Should be removed later - static var bypassWaitlist = false - init(privacyConfigurationManager: PrivacyConfigurationManaging = ContentBlocking.shared.privacyConfigurationManager, featureDisabler: DataBrokerProtectionFeatureDisabling = DataBrokerProtectionFeatureDisabler(), pixelHandler: EventMapping = DataBrokerProtectionPixelsHandler(), userDefaults: UserDefaults = .standard, - waitlistStorage: WaitlistStorage = DataBrokerProtectionWaitlist().waitlistStorage, subscriptionAvailability: SubscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability(), accountManager: AccountManager) { self.privacyConfigurationManager = privacyConfigurationManager self.featureDisabler = featureDisabler self.pixelHandler = pixelHandler self.userDefaults = userDefaults - self.waitlistStorage = waitlistStorage self.subscriptionAvailability = subscriptionAvailability self.accountManager = accountManager } - var waitlistIsOngoing: Bool { - isWaitlistEnabled && isWaitlistBetaActive - } - var isUserLocaleAllowed: Bool { var regionCode: String? if #available(macOS 13, *) { @@ -91,36 +73,12 @@ struct DefaultDataBrokerProtectionFeatureGatekeeper: DataBrokerProtectionFeature return subscriptionAvailability.isFeatureAvailable } - func isEligibleForThankYouMessage() -> Bool { - return wasWaitlistUser && isPrivacyProEnabled() - } - func disableAndDeleteForAllUsers() { featureDisabler.disableAndDelete() os_log("Disabling and removing DBP for all users", log: .dataBrokerProtection) } - func disableAndDeleteForWaitlistUsers() { - guard isWaitlistUser else { - return - } - - os_log("Disabling and removing DBP for waitlist users", log: .dataBrokerProtection) - featureDisabler.disableAndDelete() - } - - /// Returns true if a cleanup was performed, false otherwise - func cleanUpDBPForPrivacyProIfNecessary() -> Bool { - if isPrivacyProEnabled() && wasWaitlistUser && !dataBrokerProtectionCleanedUpFromWaitlistToPrivacyPro { - disableAndDeleteForWaitlistUsers() - dataBrokerProtectionCleanedUpFromWaitlistToPrivacyPro = true - return true - } else { - return false - } - } - /// If we want to prevent new users from joining the waitlist while still allowing waitlist users to continue using it, /// we should set isWaitlistEnabled to false and isWaitlistBetaActive to true. /// To remove it from everyone, isWaitlistBetaActive should be set to false @@ -129,13 +87,7 @@ struct DefaultDataBrokerProtectionFeatureGatekeeper: DataBrokerProtectionFeature guard isUserLocaleAllowed else { return false } // US internal users should have it available by default - guard !isInternalUser else { return true } - - if isWaitlistUser { - return isWaitlistBetaActive - } else { - return isWaitlistEnabled && isWaitlistBetaActive - } + return isInternalUser } func arePrerequisitesSatisfied() async -> Bool { @@ -159,35 +111,10 @@ struct DefaultDataBrokerProtectionFeatureGatekeeper: DataBrokerProtectionFeature private extension DefaultDataBrokerProtectionFeatureGatekeeper { - var dataBrokerProtectionCleanedUpFromWaitlistToPrivacyPro: Bool { - get { - return userDefaults.bool(forKey: dataBrokerProtectionKey) - } - nonmutating set { - userDefaults.set(newValue, forKey: dataBrokerProtectionKey) - } - } - var isInternalUser: Bool { NSApp.delegateTyped.internalUserDecider.isInternalUser } - var isWaitlistBetaActive: Bool { - return privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(DBPSubfeature.waitlistBetaActive) - } - - var isWaitlistEnabled: Bool { - return privacyConfigurationManager.privacyConfig.isSubfeatureEnabled(DBPSubfeature.waitlist) - } - - var isWaitlistUser: Bool { - waitlistStorage.isWaitlistUser - } - - var wasWaitlistUser: Bool { - waitlistStorage.getWaitlistInviteCode() != nil - } - func firePrerequisitePixelsAndLogIfNecessary(hasEntitlements: Bool, isAuthenticatedResult: Bool) { if !hasEntitlements { pixelHandler.fire(.gatekeeperEntitlementsInvalid) @@ -200,4 +127,3 @@ private extension DefaultDataBrokerProtectionFeatureGatekeeper { } } } -#endif diff --git a/DuckDuckGo/DBP/DataBrokerProtectionLoginItemInterface.swift b/DuckDuckGo/DBP/DataBrokerProtectionLoginItemInterface.swift index c4e86483c9c..881312dd17e 100644 --- a/DuckDuckGo/DBP/DataBrokerProtectionLoginItemInterface.swift +++ b/DuckDuckGo/DBP/DataBrokerProtectionLoginItemInterface.swift @@ -16,8 +16,6 @@ // limitations under the License. // -#if DBP - import Foundation import DataBrokerProtection import Common @@ -115,5 +113,3 @@ extension DefaultDataBrokerProtectionLoginItemInterface: DataBrokerProtectionLog return await ipcClient.getDebugMetadata() } } - -#endif diff --git a/DuckDuckGo/DBP/DataBrokerProtectionManager.swift b/DuckDuckGo/DBP/DataBrokerProtectionManager.swift index 3a181f45940..d1ba4d7367e 100644 --- a/DuckDuckGo/DBP/DataBrokerProtectionManager.swift +++ b/DuckDuckGo/DBP/DataBrokerProtectionManager.swift @@ -16,8 +16,6 @@ // limitations under the License. // -#if DBP - import Foundation import BrowserServicesKit import DataBrokerProtection @@ -31,7 +29,6 @@ public final class DataBrokerProtectionManager { private let pixelHandler: EventMapping = DataBrokerProtectionPixelsHandler() private let authenticationManager: DataBrokerProtectionAuthenticationManaging private let fakeBrokerFlag: DataBrokerDebugFlag = DataBrokerDebugFlagFakeBroker() - private let dataBrokerProtectionWaitlistDataSource: WaitlistActivationDateStore = DefaultWaitlistActivationDateStore(source: .dbp) lazy var dataManager: DataBrokerProtectionDataManager = { let dataManager = DataBrokerProtectionDataManager(pixelHandler: pixelHandler, fakeBrokerFlag: fakeBrokerFlag) @@ -68,14 +65,9 @@ public final class DataBrokerProtectionManager { extension DataBrokerProtectionManager: DataBrokerProtectionDataManagerDelegate { public func dataBrokerProtectionDataManagerDidUpdateData() { loginItemInterface.profileSaved() - - let dbpDateStore = DefaultWaitlistActivationDateStore(source: .dbp) - dbpDateStore.setActivationDateIfNecessary() } public func dataBrokerProtectionDataManagerDidDeleteData() { loginItemInterface.dataDeleted() } } - -#endif diff --git a/DuckDuckGo/DBP/DataBrokerProtectionSubscriptionEventHandler.swift b/DuckDuckGo/DBP/DataBrokerProtectionSubscriptionEventHandler.swift index 494319fa0c2..a4ed56afc85 100644 --- a/DuckDuckGo/DBP/DataBrokerProtectionSubscriptionEventHandler.swift +++ b/DuckDuckGo/DBP/DataBrokerProtectionSubscriptionEventHandler.swift @@ -15,7 +15,6 @@ // See the License for the specific language governing permissions and // limitations under the License. // -#if DBP import Combine import Foundation @@ -84,5 +83,3 @@ final class DataBrokerProtectionSubscriptionEventHandler { } } } - -#endif diff --git a/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift b/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift index d6fbfa761fc..3411cf1dc6f 100644 --- a/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift +++ b/DuckDuckGo/DBP/LoginItem+DataBrokerProtection.swift @@ -20,8 +20,6 @@ import Foundation import LoginItems import DataBrokerProtection -#if DBP - extension LoginItem { static let dbpBackgroundAgent = LoginItem(bundleId: Bundle.main.dbpBackgroundAgentBundleId, defaults: .dbp, log: .dbp) @@ -51,5 +49,3 @@ extension LoginItem: DBPLoginItemStatusChecker { return false } } - -#endif diff --git a/DuckDuckGo/Menus/MainMenu.swift b/DuckDuckGo/Menus/MainMenu.swift index ef5b69c09c6..4115217fad7 100644 --- a/DuckDuckGo/Menus/MainMenu.swift +++ b/DuckDuckGo/Menus/MainMenu.swift @@ -602,7 +602,6 @@ final class MainMenu: NSMenu { NSMenuItem(title: "Show Credentials Saved Popover", action: #selector(MainViewController.showCredentialsSavedPopover)) NSMenuItem(title: "Show Pop Up Window", action: #selector(MainViewController.showPopUpWindow)) NSMenuItem(title: "Show VPN Thank You Modal", action: #selector(MainViewController.showVPNThankYouModal)) - NSMenuItem(title: "Show PIR Thank You Modal", action: #selector(MainViewController.showPIRThankYouModal)) NSMenuItem(title: "Reset Thank You Modal Checks", action: #selector(MainViewController.resetThankYouModalChecks)) } NSMenuItem(title: "Remote Configuration") { @@ -622,10 +621,8 @@ final class MainMenu: NSMenu { .submenu(SyncDebugMenu()) .withAccessibilityIdentifier("MainMenu.syncAndBackup") -#if DBP NSMenuItem(title: "Personal Information Removal") .submenu(DataBrokerProtectionDebugMenu()) -#endif if case .normal = NSApp.runType { NSMenuItem(title: "VPN") diff --git a/DuckDuckGo/Menus/MainMenuActions.swift b/DuckDuckGo/Menus/MainMenuActions.swift index 11ad9ce9af0..3cbe45bcdcc 100644 --- a/DuckDuckGo/Menus/MainMenuActions.swift +++ b/DuckDuckGo/Menus/MainMenuActions.swift @@ -911,14 +911,6 @@ extension MainViewController { } } - @objc func showPIRThankYouModal(_ sender: Any?) { - let thankYouModalView = WaitlistBetaThankYouDialogViewController(copy: .dbp) - let thankYouWindowController = thankYouModalView.wrappedInWindowController() - if let thankYouWindow = thankYouWindowController.window { - WindowsManager.windows.first?.beginSheet(thankYouWindow) - } - } - @objc func resetEmailProtectionInContextPrompt(_ sender: Any?) { EmailManager().resetEmailProtectionInContextPrompt() } diff --git a/DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift b/DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift index d5bea3cc014..085e84e1fad 100644 --- a/DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift +++ b/DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift @@ -40,9 +40,7 @@ protocol OptionsButtonMenuDelegate: AnyObject { func optionsButtonMenuRequestedPreferences(_ menu: NSMenu) func optionsButtonMenuRequestedAppearancePreferences(_ menu: NSMenu) func optionsButtonMenuRequestedAccessibilityPreferences(_ menu: NSMenu) -#if DBP func optionsButtonMenuRequestedDataBrokerProtection(_ menu: NSMenu) -#endif func optionsButtonMenuRequestedSubscriptionPurchasePage(_ menu: NSMenu) func optionsButtonMenuRequestedSubscriptionPreferences(_ menu: NSMenu) func optionsButtonMenuRequestedIdentityTheftRestoration(_ menu: NSMenu) @@ -146,11 +144,9 @@ final class MoreOptionsMenu: NSMenu { addItem(preferencesItem) } -#if DBP @objc func openDataBrokerProtection(_ sender: NSMenuItem) { actionDelegate?.optionsButtonMenuRequestedDataBrokerProtection(self) } -#endif // DBP @objc func showNetworkProtectionStatus(_ sender: NSMenuItem) { actionDelegate?.optionsButtonMenuRequestedNetworkProtectionPopover(self) @@ -835,8 +831,6 @@ final class SubscriptionSubMenu: NSMenu, NSMenuDelegate { self.networkProtectionItem.isEnabled = isNetworkProtectionItemEnabled self.dataBrokerProtectionItem.isEnabled = isDataBrokerProtectionItemEnabled self.identityTheftRestorationItem.isEnabled = isIdentityTheftRestorationItemEnabled - - DataBrokerProtectionExternalWaitlistPixels.fire(pixel: GeneralPixel.dataBrokerProtectionWaitlistEntryPointMenuItemDisplayed, frequency: .dailyAndCount) } } } diff --git a/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift b/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift index 7f1b74a7df6..a8eee48ad4e 100644 --- a/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift +++ b/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift @@ -1012,11 +1012,9 @@ extension NavigationBarViewController: NSMenuDelegate { extension NavigationBarViewController: OptionsButtonMenuDelegate { -#if DBP func optionsButtonMenuRequestedDataBrokerProtection(_ menu: NSMenu) { WindowControllersManager.shared.showDataBrokerProtectionTab() } -#endif func optionsButtonMenuRequestedOpenExternalPasswordManager(_ menu: NSMenu) { BWManager.shared.openBitwarden() diff --git a/DuckDuckGo/Tab/View/BrowserTabViewController.swift b/DuckDuckGo/Tab/View/BrowserTabViewController.swift index 779e35dc471..36494384056 100644 --- a/DuckDuckGo/Tab/View/BrowserTabViewController.swift +++ b/DuckDuckGo/Tab/View/BrowserTabViewController.swift @@ -138,7 +138,6 @@ final class BrowserTabViewController: NSViewController { name: .emailDidCloseEmailProtection, object: nil) -#if DBP NotificationCenter.default.addObserver(self, selector: #selector(onDBPFeatureDisabled), name: .dbpWasDisabled, @@ -147,12 +146,6 @@ final class BrowserTabViewController: NSViewController { selector: #selector(onCloseDataBrokerProtection), name: .dbpDidClose, object: nil) - NotificationCenter.default.addObserver(self, - selector: #selector(onDataBrokerWaitlistGetStartedPressedByUser), - name: .dataBrokerProtectionUserPressedOnGetStartedOnWaitlist, - object: nil) - -#endif NotificationCenter.default.addObserver(self, selector: #selector(onCloseSubscriptionPage), @@ -195,7 +188,6 @@ final class BrowserTabViewController: NSViewController { self.previouslySelectedTab = nil } -#if DBP @objc private func onDBPFeatureDisabled(_ notification: Notification) { Task { @MainActor in @@ -221,8 +213,6 @@ final class BrowserTabViewController: NSViewController { WindowControllersManager.shared.showDataBrokerProtectionTab() } -#endif - @objc private func onCloseSubscriptionPage(_ notification: Notification) { guard let activeTab = tabViewModel?.tab else { return } @@ -288,13 +278,11 @@ final class BrowserTabViewController: NSViewController { private func removeDataBrokerViewIfNecessary() -> ([Tab]) -> Void { { [weak self] (tabs: [Tab]) in guard let self else { return } -#if DBP if let dataBrokerProtectionHomeViewController, !tabs.contains(where: { $0.content == .dataBrokerProtection }) { dataBrokerProtectionHomeViewController.removeCompletely() self.dataBrokerProtectionHomeViewController = nil } -#endif } } @@ -557,9 +545,7 @@ final class BrowserTabViewController: NSViewController { preferencesViewController?.removeCompletely() bookmarksViewController?.removeCompletely() homePageViewController?.removeCompletely() -#if DBP dataBrokerProtectionHomeViewController?.removeCompletely() -#endif if includingWebView { self.removeWebViewFromHierarchy() } @@ -611,13 +597,11 @@ final class BrowserTabViewController: NSViewController { removeAllTabContent() addAndLayoutChild(homePageViewControllerCreatingIfNeeded()) -#if DBP case .dataBrokerProtection: removeAllTabContent() let dataBrokerProtectionViewController = dataBrokerProtectionHomeViewControllerCreatingIfNeeded() self.previouslySelectedTab = tabCollectionViewModel.selectedTab addAndLayoutChild(dataBrokerProtectionViewController) -#endif default: removeAllTabContent() } @@ -695,7 +679,6 @@ final class BrowserTabViewController: NSViewController { }() } -#if DBP // MARK: - DataBrokerProtection var dataBrokerProtectionHomeViewController: DBPHomeViewController? @@ -706,7 +689,6 @@ final class BrowserTabViewController: NSViewController { return dataBrokerProtectionHomeViewController }() } -#endif // MARK: - Preferences diff --git a/DuckDuckGo/Waitlist/Storage/WaitlistActivationDateStore.swift b/DuckDuckGo/Waitlist/Storage/WaitlistActivationDateStore.swift index c355e196df5..1b6d1237677 100644 --- a/DuckDuckGo/Waitlist/Storage/WaitlistActivationDateStore.swift +++ b/DuckDuckGo/Waitlist/Storage/WaitlistActivationDateStore.swift @@ -20,19 +20,16 @@ import Foundation enum WaitlistActivationDateStoreSource { case netP - case dbp var activationDateKey: String { switch self { case .netP: return "com.duckduckgo.network-protection.activation-date" - case .dbp: return "com.duckduckgo.dbp.activation-date" } } var lastActiveDateKey: String { switch self { case .netP: return "com.duckduckgo.network-protection.last-active-date" - case .dbp: return "com.duckduckgo.dbp.last-active-date" } } } @@ -54,8 +51,6 @@ struct DefaultWaitlistActivationDateStore: WaitlistActivationDateStore { switch source { case.netP: self.userDefaults = .netP - case .dbp: - self.userDefaults = .dbp } } diff --git a/DuckDuckGo/Waitlist/Views/WaitlistRootView.swift b/DuckDuckGo/Waitlist/Views/WaitlistRootView.swift deleted file mode 100644 index b9a029d4c6d..00000000000 --- a/DuckDuckGo/Waitlist/Views/WaitlistRootView.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// WaitlistRootView.swift -// -// Copyright © 2023 DuckDuckGo. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import SwiftUI - -#if DBP - -import SwiftUI - -struct DataBrokerProtectionWaitlistRootView: View { - @EnvironmentObject var model: WaitlistViewModel - - var body: some View { - Group { - switch model.viewState { - case .notOnWaitlist, .joiningWaitlist: - JoinWaitlistView(viewData: DataBrokerProtectionJoinWaitlistViewData()) - case .joinedWaitlist(let state): - JoinedWaitlistView(viewData: DataBrokerProtectionJoinedWaitlistViewData(), - notificationsAllowed: state == .notificationAllowed) - case .invited: - InvitedToWaitlistView(viewData: DataBrokerProtectionInvitedToWaitlistViewData()) - case .termsAndConditions: - WaitlistTermsAndConditionsView(viewData: DataBrokerProtectionWaitlistTermsAndConditionsViewData()) { - DataBrokerProtectionTermsAndConditionsContentView() - } - case .readyToEnable: - // Hack to skip the readyToEnable step and close the modal - Text("") - .onAppear { - Task { - await model.perform(action: .closeAndConfirmFeature) - } - } - } - } - .environmentObject(model) - } -} - -#endif diff --git a/DuckDuckGo/Waitlist/Views/WaitlistSteps/InvitedToWaitlistView.swift b/DuckDuckGo/Waitlist/Views/WaitlistSteps/InvitedToWaitlistView.swift index ca30a44deb6..52c1219a1ae 100644 --- a/DuckDuckGo/Waitlist/Views/WaitlistSteps/InvitedToWaitlistView.swift +++ b/DuckDuckGo/Waitlist/Views/WaitlistSteps/InvitedToWaitlistView.swift @@ -116,17 +116,3 @@ struct WaitlistEntryViewItemViewData: Identifiable { let title: String let subtitle: String } - -#if DBP - -struct DataBrokerProtectionInvitedToWaitlistViewData: InvitedToWaitlistViewData { - let headerImageName = "Gift-96" - let title = UserText.dataBrokerProtectionWaitlistInvitedTitle - let subtitle = UserText.dataBrokerProtectionWaitlistInvitedSubtitle - let buttonDismissLabel = UserText.dataBrokerProtectionWaitlistButtonDismiss - let buttonGetStartedLabel = UserText.dataBrokerProtectionWaitlistButtonGetStarted - let availabilityDisclaimer = UserText.dataBrokerProtectionWaitlistAvailabilityDisclaimer - let entryViewViewDataList = [WaitlistEntryViewItemViewData]() -} - -#endif diff --git a/DuckDuckGo/Waitlist/Views/WaitlistSteps/JoinWaitlistView.swift b/DuckDuckGo/Waitlist/Views/WaitlistSteps/JoinWaitlistView.swift index 6c0e4deb2a1..e1b4741d652 100644 --- a/DuckDuckGo/Waitlist/Views/WaitlistSteps/JoinWaitlistView.swift +++ b/DuckDuckGo/Waitlist/Views/WaitlistSteps/JoinWaitlistView.swift @@ -72,17 +72,3 @@ struct JoinWaitlistView: View { .environmentObject(model) } } - -#if DBP - -struct DataBrokerProtectionJoinWaitlistViewData: JoinWaitlistViewViewData { - let headerImageName = "DBP-Information-Remover" - let title = UserText.dataBrokerProtectionWaitlistJoinTitle - let subtitle1 = UserText.dataBrokerProtectionWaitlistInvitedSubtitle - let subtitle2 = "" - let availabilityDisclaimer = UserText.dataBrokerProtectionWaitlistAvailabilityDisclaimer - let buttonCloseLabel = UserText.dataBrokerProtectionWaitlistButtonClose - let buttonJoinWaitlistLabel = UserText.dataBrokerProtectionWaitlistButtonJoinWaitlist -} - -#endif diff --git a/DuckDuckGo/Waitlist/Views/WaitlistSteps/JoinedWaitlistView.swift b/DuckDuckGo/Waitlist/Views/WaitlistSteps/JoinedWaitlistView.swift index 553d3e65622..0ca30ddd353 100644 --- a/DuckDuckGo/Waitlist/Views/WaitlistSteps/JoinedWaitlistView.swift +++ b/DuckDuckGo/Waitlist/Views/WaitlistSteps/JoinedWaitlistView.swift @@ -84,18 +84,3 @@ struct JoinedWaitlistView: View { .environmentObject(model) } } - -#if DBP - -struct DataBrokerProtectionJoinedWaitlistViewData: JoinedWaitlistViewData { - let headerImageName = "JoinedWaitlistHeader" - var title = UserText.dataBrokerProtectionWaitlistJoinedTitle - var joinedWithNoNotificationSubtitle1 = UserText.dataBrokerProtectionWaitlistJoinedWithNotificationsSubtitle1 - var joinedWithNoNotificationSubtitle2 = UserText.dataBrokerProtectionWaitlistJoinedWithNotificationsSubtitle2 - var enableNotificationSubtitle = UserText.dataBrokerProtectionWaitlistEnableNotifications - var buttonConfirmLabel = UserText.dataBrokerProtectionWaitlistButtonDone - var buttonCancelLabel = UserText.dataBrokerProtectionWaitlistButtonNoThanks - var buttonEnableNotificationLabel = UserText.dataBrokerProtectionWaitlistButtonEnableNotifications -} - -#endif diff --git a/DuckDuckGo/Waitlist/Views/WaitlistSteps/WaitlistTermsAndConditionsView.swift b/DuckDuckGo/Waitlist/Views/WaitlistSteps/WaitlistTermsAndConditionsView.swift index 7495ae9e0b6..38b01473ff7 100644 --- a/DuckDuckGo/Waitlist/Views/WaitlistSteps/WaitlistTermsAndConditionsView.swift +++ b/DuckDuckGo/Waitlist/Views/WaitlistSteps/WaitlistTermsAndConditionsView.swift @@ -81,134 +81,3 @@ private extension Text { } } - -#if DBP - -struct DataBrokerProtectionTermsAndConditionsContentView: View { - private let groupLeadingPadding: CGFloat = 15.0 - private let sectionBottomPadding: CGFloat = 10.0 - - var body: some View { - VStack(alignment: .leading, spacing: 5) { - - Text(verbatim: UserText.dataBrokerProtectionPrivacyPolicyTitle) - .font(.system(size: 15, weight: .bold)) - .multilineTextAlignment(.leading) - - Text(verbatim: "\nWe don’t save your personal information for this service to function.") - .fontWeight(.bold) - .padding(.bottom, sectionBottomPadding) - - Group { - Text(verbatim: "• This Privacy Policy is for our waitlist beta service.") - HStack(spacing: 0) { - Text(verbatim: "• Our main ") - Text(verbatim: "Privacy Policy ") - .foregroundColor(Color.blue) - .underline(color: .blue) - .onTapGesture { - let url = URL(string: "https://duckduckgo.com/privacy")! - WindowsManager.openNewWindow(with: url, source: .ui, isBurner: false) - } - Text(verbatim: "also applies here.") - } - Text(verbatim: "• This beta product may collect more diagnostic data than our typical products. Examples of such data include: alerts of low memory, application restarts, and user engagement with product features.") - } - .padding(.leading, groupLeadingPadding) - - Text(verbatim: "\nYour personal information is stored locally on your device.") - .fontWeight(.bold) - .padding(.bottom, sectionBottomPadding) - - Group { - Text(verbatim: "• The information you provide when you sign-up to use this service, for example your name, age, address, and phone number is stored on your device.") - Text(verbatim: "• We then scan data brokers from your device to check if any sites contain your personal information.") - Text(verbatim: "• We may find additional information on data broker sites through this scanning process, like alternative names or phone numbers, or the names of your relatives. This information is also stored locally on your device.") - } - .padding(.leading, groupLeadingPadding) - - Text(verbatim: "\nWe submit removal requests to data broker sites on your behalf.") - .fontWeight(.bold) - .padding(.bottom, sectionBottomPadding) - - Group { - Text(verbatim: "• We submit removal requests to the data broker sites directly from your device, unlike other services where the removal process is initiated on remote servers.") - Text(verbatim: "• The only personal information we may receive is a confirmation email from data broker sites which is deleted within 72 hours.") - Text(verbatim: "• We regularly re-scan data broker sites to check on the removal status of your information. If it has reappeared, we resubmit the removal request.") - } - .padding(.leading, groupLeadingPadding) - - Text(verbatim: "\nTerms of Service") - .fontWeight(.bold) - - Text(verbatim: "You must be eligible to use this service.") - .fontWeight(.bold) - .padding(.bottom, sectionBottomPadding) - - Group { - Text(verbatim: "• To use this service, you must be 18 or older.") - } - .padding(.leading, groupLeadingPadding) - - Text(verbatim: "\nThe service is for limited and personal use only.") - .fontWeight(.bold) - .padding(.bottom, sectionBottomPadding) - - Group { - Text(verbatim: "• The service is available for your personal use only. You represent and warrant that you will only initiate removal of your own personal information.") - Text(verbatim: "• This service is available on one device only.") - } - .padding(.leading, groupLeadingPadding) - - Text(verbatim: "\nYou give DuckDuckGo authority to act on your Here's an updated version with the remaining content:") - .fontWeight(.bold) - .padding(.bottom, sectionBottomPadding) - - Group { - Text(verbatim: "• You hereby authorize DuckDuckGo to act on your behalf to request removal of your personal information from data broker sites.") - Text(verbatim: "• Because data broker sites often have multi-step processes required to have information removed, and because they regularly update their databases with new personal information, this authorization includes ongoing action on your behalf solely to perform the service.") - } - .padding(.leading, groupLeadingPadding) - - Text(verbatim: "\nThe service cannot remove all of your information from the Internet.") - .fontWeight(.bold) - .padding(.bottom, sectionBottomPadding) - - Group { - Text(verbatim: "• This service requests removal from a limited number of data broker sites only. You understand that we cannot guarantee that the third-party sites will honor the requests, or that your personal information will not reappear in the future.") - Text(verbatim: "• You understand that we will only be able to request the removal of information based upon the information you provide to us.") - } - .padding(.leading, groupLeadingPadding) - - Text(verbatim: "\nWe provide this beta service as-is, and without warranty.") - .fontWeight(.bold) - .padding(.bottom, sectionBottomPadding) - - Group { - Text(verbatim: "• This service is provided as-is and without warranties or guarantees of any kind.") - Text(verbatim: "• To the extent possible under applicable law, DuckDuckGo will not be liable for any damage or loss arising from your use of the service. In any event, the total aggregate liability of DuckDuckGo shall not exceed $25 or the equivalent in your local currency.") - Text(verbatim: "• We may in the future transfer responsibility for the service to a subsidiary of DuckDuckGo. If that happens, you agree that references to “DuckDuckGo” will refer to our subsidiary, which will then become responsible for providing the service and for any liabilities relating to it.") - } - .padding(.leading, groupLeadingPadding) - - Text(verbatim: "\nWe may terminate access at any time.") - .fontWeight(.bold) - .padding(.bottom, sectionBottomPadding) - - Group { - Text(verbatim: "• This service is in beta, and your access to it is temporary.") - Text(verbatim: "• We reserve the right to terminate access at any time in our sole discretion, including for violation of these terms or our DuckDuckGo Terms of Service, which are incorporated by reference.") - } - .padding(.leading, groupLeadingPadding) - - }.padding(.all, 20) - } -} - -struct DataBrokerProtectionWaitlistTermsAndConditionsViewData: WaitlistTermsAndConditionsViewData { - let title = "Personal Information Removal Beta\nService Terms and Privacy Policy" - let buttonCancelLabel = UserText.dataBrokerProtectionWaitlistButtonCancel - let buttonAgreeAndContinueLabel = UserText.dataBrokerProtectionWaitlistButtonAgreeAndContinue -} - -#endif diff --git a/DuckDuckGo/Waitlist/Views/WaitlistThankYouPromptPresenter.swift b/DuckDuckGo/Waitlist/Views/WaitlistThankYouPromptPresenter.swift index fe79b7cc96a..67cc8eaf590 100644 --- a/DuckDuckGo/Waitlist/Views/WaitlistThankYouPromptPresenter.swift +++ b/DuckDuckGo/Waitlist/Views/WaitlistThankYouPromptPresenter.swift @@ -25,20 +25,11 @@ final class WaitlistThankYouPromptPresenter { private enum Constants { static let didShowThankYouPromptKey = "duckduckgo.macos.browser.did-show-thank-you-prompt" - static let didDismissPIRCardKey = "duckduckgo.macos.browser.did-dismiss-pir-card" } - private let isPIRBetaTester: () -> Bool private let userDefaults: UserDefaults - convenience init() { - self.init(isPIRBetaTester: { - false - }) - } - - init(isPIRBetaTester: @escaping () -> Bool, userDefaults: UserDefaults = .standard) { - self.isPIRBetaTester = isPIRBetaTester + init(userDefaults: UserDefaults = .standard) { self.userDefaults = userDefaults } @@ -51,30 +42,12 @@ final class WaitlistThankYouPromptPresenter { guard canShowPromptCheck() else { return } - - if isPIRBetaTester() { - saveDidShowPromptCheck() - presentPIRThankYouPrompt(in: window) - } - } - - @MainActor - func presentPIRThankYouPrompt(in window: NSWindow) { - let thankYouModalView = WaitlistBetaThankYouDialogViewController(copy: .dbp) - let thankYouWindowController = thankYouModalView.wrappedInWindowController() - if let thankYouWindow = thankYouWindowController.window { - window.beginSheet(thankYouWindow) - } } // MARK: - Eligibility var canShowPIRCard: Bool { - guard !self.userDefaults.bool(forKey: Constants.didDismissPIRCardKey) else { - return false - } - - return isPIRBetaTester() + return false } func canShowPromptCheck() -> Bool { @@ -83,10 +56,6 @@ final class WaitlistThankYouPromptPresenter { // MARK: - Dismissal - func didDismissPIRThankYouCard() { - self.userDefaults.setValue(true, forKey: Constants.didDismissPIRCardKey) - } - private func saveDidShowPromptCheck() { self.userDefaults.setValue(true, forKey: Constants.didShowThankYouPromptKey) } @@ -95,7 +64,6 @@ final class WaitlistThankYouPromptPresenter { func resetPromptCheck() { self.userDefaults.removeObject(forKey: Constants.didShowThankYouPromptKey) - self.userDefaults.removeObject(forKey: Constants.didDismissPIRCardKey) } } diff --git a/DuckDuckGo/Waitlist/Views/WaitlistThankYouView.swift b/DuckDuckGo/Waitlist/Views/WaitlistThankYouView.swift index b94d1846d2a..541f94ff73a 100644 --- a/DuckDuckGo/Waitlist/Views/WaitlistThankYouView.swift +++ b/DuckDuckGo/Waitlist/Views/WaitlistThankYouView.swift @@ -23,13 +23,6 @@ import SwiftUI // MARK: - Model struct WaitlistBetaThankYouCopy { - static let dbp = WaitlistBetaThankYouCopy( - title: UserText.dbpThankYouTitle, - subtitle: UserText.dbpThankYouSubtitle, - body1: UserText.dbpThankYouBody1, - body2: UserText.dbpThankYouBody2 - ) - static let vpn = WaitlistBetaThankYouCopy( title: UserText.vpnThankYouTitle, subtitle: UserText.vpnThankYouSubtitle, diff --git a/DuckDuckGo/Waitlist/Views/WaitlistViewControllerPresenter.swift b/DuckDuckGo/Waitlist/Views/WaitlistViewControllerPresenter.swift index 55ee0e65844..360dfda449c 100644 --- a/DuckDuckGo/Waitlist/Views/WaitlistViewControllerPresenter.swift +++ b/DuckDuckGo/Waitlist/Views/WaitlistViewControllerPresenter.swift @@ -29,50 +29,3 @@ extension WaitlistViewControllerPresenter { Self.show(completion: nil) } } - -#if DBP - -struct DataBrokerProtectionWaitlistViewControllerPresenter: WaitlistViewControllerPresenter { - - static func shouldPresentWaitlist() -> Bool { - if DefaultSubscriptionFeatureAvailability().isFeatureAvailable { - return false - } - - let waitlist = DataBrokerProtectionWaitlist() - - let accepted = UserDefaults().bool(forKey: UserDefaultsWrapper.Key.dataBrokerProtectionTermsAndConditionsAccepted.rawValue) - - return !(waitlist.waitlistStorage.isInvited && accepted) - } - - @MainActor - static func show(completion: (() -> Void)? = nil) { - guard let windowController = WindowControllersManager.shared.lastKeyMainWindowController else { - return - } - DataBrokerProtectionExternalWaitlistPixels.fire(pixel: GeneralPixel.dataBrokerProtectionWaitlistIntroDisplayed, frequency: .dailyAndCount) - - // This is a hack to get around an issue with the waitlist notification screen showing the wrong state while it animates in, and then - // jumping to the correct state as soon as the animation is complete. This works around that problem by providing the correct state up front, - // preventing any state changing from occurring. - UNUserNotificationCenter.current().getNotificationSettings { settings in - let status = settings.authorizationStatus - let state = WaitlistViewModel.NotificationPermissionState.from(status) - DispatchQueue.main.async { - let viewModel = WaitlistViewModel(waitlist: DataBrokerProtectionWaitlist(), - notificationPermissionState: state, - showNotificationSuccessState: false, - termsAndConditionActionHandler: DataBrokerProtectionWaitlistTermsAndConditionsActionHandler(), - featureSetupHandler: DataBrokerProtectionWaitlistFeatureSetupHandler()) - - let viewController = WaitlistModalViewController(viewModel: viewModel, contentView: DataBrokerProtectionWaitlistRootView()) - windowController.mainViewController.beginSheet(viewController) { _ in - completion?() - } - } - } - } -} - -#endif diff --git a/DuckDuckGo/Waitlist/Waitlist.swift b/DuckDuckGo/Waitlist/Waitlist.swift index 4ed31b5b082..27ac30ced12 100644 --- a/DuckDuckGo/Waitlist/Waitlist.swift +++ b/DuckDuckGo/Waitlist/Waitlist.swift @@ -64,8 +64,6 @@ enum WaitlistInviteCodeFetchError: Error, Equatable { extension Notification.Name { static let networkProtectionWaitlistAccessChanged = Notification.Name(rawValue: "networkProtectionWaitlistAccessChanged") - static let dataBrokerProtectionWaitlistAccessChanged = Notification.Name(rawValue: "dataBrokerProtectionWaitlistAccessChanged") - static let dataBrokerProtectionUserPressedOnGetStartedOnWaitlist = Notification.Name(rawValue: "dataBrokerProtectionUserPressedOnGetStartedOnWaitlist") } @@ -153,85 +151,3 @@ extension ProductWaitlistRequest { self.init(productName: productName, makeHTTPRequest: makeHTTPRequest) } } - -#if DBP - -// MARK: - DataBroker Protection Waitlist - -import DataBrokerProtection - -struct DataBrokerProtectionWaitlist: Waitlist { - - static let identifier: String = "databrokerprotection" - static let apiProductName: String = "dbp" - static let keychainAppGroup: String = Bundle.main.appGroup(bundle: .dbp) - - static let notificationIdentifier = "com.duckduckgo.macos.browser.data-broker-protection.invite-code-available" - static let inviteAvailableNotificationTitle = UserText.dataBrokerProtectionWaitlistNotificationTitle - static let inviteAvailableNotificationBody = UserText.dataBrokerProtectionWaitlistNotificationText - - let waitlistStorage: WaitlistStorage - let waitlistRequest: WaitlistRequest - - private let redeemUseCase: DataBrokerProtectionRedeemUseCase - private let redeemAuthenticationRepository: AuthenticationRepository - - var readyToAcceptTermsAndConditions: Bool { - let accepted = UserDefaults().bool(forKey: UserDefaultsWrapper.Key.dataBrokerProtectionTermsAndConditionsAccepted.rawValue) - return waitlistStorage.isInvited && !accepted - } - - init() { - self.init( - store: WaitlistKeychainStore(waitlistIdentifier: Self.identifier, keychainAppGroup: Self.keychainAppGroup), - request: ProductWaitlistRequest(productName: Self.apiProductName), - redeemUseCase: RedeemUseCase(), - redeemAuthenticationRepository: KeychainAuthenticationData() - ) - } - - init(store: WaitlistStorage, request: WaitlistRequest, - redeemUseCase: DataBrokerProtectionRedeemUseCase, - redeemAuthenticationRepository: AuthenticationRepository) { - self.waitlistStorage = store - self.waitlistRequest = request - self.redeemUseCase = redeemUseCase - self.redeemAuthenticationRepository = redeemAuthenticationRepository - } - - private func fetchInviteCode() async throws -> String { - - // First check if we have it stored locally - if let inviteCode = waitlistStorage.getWaitlistInviteCode() { - return inviteCode - } - - // If not, then try to fetch it remotely - _ = await fetchInviteCodeIfAvailable() - - // Try to fetch it from storage again - if let inviteCode = waitlistStorage.getWaitlistInviteCode() { - return inviteCode - } else { - throw WaitlistInviteCodeFetchError.noCodeAvailable - } - } - - private func redeemInviteCode(_ inviteCode: String) async throws { - os_log("Redeeming DBP invite code...", log: .dataBrokerProtection) - - try await redeemUseCase.redeem(inviteCode: inviteCode) - NotificationCenter.default.post(name: .dataBrokerProtectionWaitlistAccessChanged, object: nil) - - os_log("DBP invite code redeemed", log: .dataBrokerProtection) - UserDefaults().setValue(true, forKey: UserDefaultsWrapper.Key.shouldShowDBPWaitlistInvitedCardUI.rawValue) - - sendInviteCodeAvailableNotification { - DispatchQueue.main.async { - DataBrokerProtectionExternalWaitlistPixels.fire(pixel: GeneralPixel.dataBrokerProtectionWaitlistNotificationShown, frequency: .dailyAndCount) - } - } - } -} - -#endif diff --git a/DuckDuckGo/Waitlist/WaitlistFeatureSetupHandler.swift b/DuckDuckGo/Waitlist/WaitlistFeatureSetupHandler.swift index 6c2c63b5632..a849b9b62ac 100644 --- a/DuckDuckGo/Waitlist/WaitlistFeatureSetupHandler.swift +++ b/DuckDuckGo/Waitlist/WaitlistFeatureSetupHandler.swift @@ -28,15 +28,3 @@ struct NetworkProtectionWaitlistFeatureSetupHandler: WaitlistFeatureSetupHandler NotificationCenter.default.post(name: .networkProtectionWaitlistAccessChanged, object: nil) } } - -#if DBP - -struct DataBrokerProtectionWaitlistFeatureSetupHandler: WaitlistFeatureSetupHandler { - func confirmFeature() { - NotificationCenter.default.post(name: .dataBrokerProtectionWaitlistAccessChanged, object: nil) - NotificationCenter.default.post(name: .dataBrokerProtectionUserPressedOnGetStartedOnWaitlist, object: nil) - UserDefaults().setValue(false, forKey: UserDefaultsWrapper.Key.shouldShowDBPWaitlistInvitedCardUI.rawValue) - } -} - -#endif diff --git a/DuckDuckGo/Waitlist/WaitlistTermsAndConditionsActionHandler.swift b/DuckDuckGo/Waitlist/WaitlistTermsAndConditionsActionHandler.swift index 3f6f456ea06..8e0e4d3dfb5 100644 --- a/DuckDuckGo/Waitlist/WaitlistTermsAndConditionsActionHandler.swift +++ b/DuckDuckGo/Waitlist/WaitlistTermsAndConditionsActionHandler.swift @@ -25,24 +25,3 @@ protocol WaitlistTermsAndConditionsActionHandler { func didShow() mutating func didAccept() } - -#if DBP - -struct DataBrokerProtectionWaitlistTermsAndConditionsActionHandler: WaitlistTermsAndConditionsActionHandler { - @UserDefaultsWrapper(key: .dataBrokerProtectionTermsAndConditionsAccepted, defaultValue: false) - var acceptedTermsAndConditions: Bool - - func didShow() { - PixelKit.fire(GeneralPixel.dataBrokerProtectionWaitlistTermsAndConditionsDisplayed, frequency: .dailyAndCount) - } - - mutating func didAccept() { - acceptedTermsAndConditions = true - // Remove delivered NetP notifications in case the user didn't click them. - UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: [DataBrokerProtectionWaitlist.notificationIdentifier]) - - PixelKit.fire(GeneralPixel.dataBrokerProtectionWaitlistTermsAndConditionsAccepted, frequency: .dailyAndCount) - } -} - -#endif diff --git a/DuckDuckGo/Windows/View/WindowControllersManager.swift b/DuckDuckGo/Windows/View/WindowControllersManager.swift index e21c96bc99e..3cbb3630d86 100644 --- a/DuckDuckGo/Windows/View/WindowControllersManager.swift +++ b/DuckDuckGo/Windows/View/WindowControllersManager.swift @@ -115,11 +115,9 @@ final class WindowControllersManager: WindowControllersManagerProtocol { extension WindowControllersManager { -#if DBP func showDataBrokerProtectionTab() { showTab(with: .dataBrokerProtection) } -#endif func showBookmarksTab() { showTab(with: .bookmarks) diff --git a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionPixelTests.swift b/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionPixelTests.swift deleted file mode 100644 index 1d32a2e7626..00000000000 --- a/LocalPackages/DataBrokerProtection/Tests/DataBrokerProtectionTests/DataBrokerProtectionPixelTests.swift +++ /dev/null @@ -1,149 +0,0 @@ -// -// DataBrokerProtectionPixelTests.swift -// -// Copyright © 2023 DuckDuckGo. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -#if DBP - -import DataBrokerProtection -import Networking -import Foundation -import PixelKit -import PixelKitTestingUtilities -import XCTest -@testable import DuckDuckGo_Privacy_Browser - -/// Tests to ensure that DBP pixels sent from the main app work well -/// -final class DataBrokerProtectionPixelTests: XCTestCase { - - struct PixelDataStoreMock: PixelDataStore { - func set(_ value: Int, forKey: String, completionHandler: ((Error?) -> Void)?) { - completionHandler?(nil) - } - - func set(_ value: String, forKey: String, completionHandler: ((Error?) -> Void)?) { - completionHandler?(nil) - } - - func set(_ value: Double, forKey: String, completionHandler: ((Error?) -> Void)?) { - completionHandler?(nil) - } - - func value(forKey key: String) -> Double? { - nil - } - - func value(forKey key: String) -> Int? { - nil - } - - func value(forKey key: String) -> String? { - nil - } - - func removeValue(forKey key: String, completionHandler: ((Error?) -> Void)?) { - completionHandler?(nil) - } - } - - func mapToPixelEvent(_ dbpPixel: DataBrokerProtectionPixels) -> Pixel.Event { - switch dbpPixel { - case .error(let error, _): - return .debug(event: .pixelKitEvent(dbpPixel), error: error) - default: - return .pixelKitEvent(dbpPixel) - } - } - - /// This method implements validation logic that can be used to test several events. - /// - func validatePixel(for dbpEvent: DataBrokerProtectionPixels) { - let inAppVersion = "1.0.1" - let inUserAgent = "ddg_mac/\(inAppVersion) (com.duckduckgo.macos.browser.dbp.debug; macOS Version 14.0 (Build 23A344))" - - // We want to make sure the callback is executed exactly once to validate - // all of the fire parameters - let callbackExecuted = expectation(description: "We expect the callback to be executed once") - callbackExecuted.expectedFulfillmentCount = 1 - callbackExecuted.assertForOverFulfill = true - - // This is annoyingly necessary to test the user agent right now - APIRequest.Headers.setUserAgent(inUserAgent) - - let storeMock = PixelDataStoreMock() - - let inEvent = mapToPixelEvent(dbpEvent) - - let pixel = Pixel(appVersion: inAppVersion, store: storeMock) { (event, parameters, _, headers, onComplete) in - - // Validate that the event is the one we expect - XCTAssertEqual(event, inEvent) - - // Validate that the basic params are present - let pixelRequestValidator = PixelRequestValidator() - pixelRequestValidator.validateBasicPixelParams(expectedAppVersion: inAppVersion, expectedUserAgent: inUserAgent, requestParameters: parameters, requestHeaders: headers.httpHeaders) - - // Validate that the debug params are present - if case .debug(let wrappedEvent, let error) = inEvent { - XCTAssertEqual("m_mac_debug_\(wrappedEvent.name)", inEvent.name) - - pixelRequestValidator.validateDebugPixelParams(expectedError: error, requestParameters: parameters) - } - - // Validate that the dbp-specific params are present in the fire event parameters - XCTAssertTrue( - dbpEvent.params?.allSatisfy({ key, value in - parameters[key] == value - }) ?? false) - - callbackExecuted.fulfill() - onComplete(nil) - } - - pixel.fire(inEvent, withAdditionalParameters: dbpEvent.params) - - waitForExpectations(timeout: 0.1) - } - - func testBasicPixelValidation() { - let inDataBroker = "inDataBroker" - - let eventsToTest: [DataBrokerProtectionPixels] = [ - .error(error: DataBrokerProtectionError.cancelled, dataBroker: inDataBroker), - .parentChildMatches(parent: "a", child: "b", value: 5), - .optOutStart(dataBroker: "a", attemptId: UUID()), - .optOutEmailGenerate(dataBroker: "a", attemptId: UUID(), duration: 5), - .optOutCaptchaParse(dataBroker: "a", attemptId: UUID(), duration: 5), - .optOutCaptchaSend(dataBroker: "a", attemptId: UUID(), duration: 5), - .optOutCaptchaSolve(dataBroker: "a", attemptId: UUID(), duration: 5), - .optOutSubmit(dataBroker: "a", attemptId: UUID(), duration: 5), - .optOutEmailReceive(dataBroker: "a", attemptId: UUID(), duration: 5), - .optOutEmailConfirm(dataBroker: "a", attemptId: UUID(), duration: 5), - .optOutValidate(dataBroker: "a", attemptId: UUID(), duration: 5), - .optOutFinish(dataBroker: "a", attemptId: UUID(), duration: 5), - .optOutSubmitSuccess(dataBroker: "a", attemptId: UUID(), duration: 5), - .optOutSuccess(dataBroker: "a", attemptId: UUID(), duration: 5), - .optOutFailure(dataBroker: "a", attemptId: UUID(), duration: 5, stage: "some") - ] - - for event in eventsToTest { - validatePixel(for: event) - } - } -} - -#endif diff --git a/UnitTests/DBP/Tests/DataBrokerProtectionFeatureGatekeeperTests.swift b/UnitTests/DBP/Tests/DataBrokerProtectionFeatureGatekeeperTests.swift index 7f70a0e8055..f85d03a145a 100644 --- a/UnitTests/DBP/Tests/DataBrokerProtectionFeatureGatekeeperTests.swift +++ b/UnitTests/DBP/Tests/DataBrokerProtectionFeatureGatekeeperTests.swift @@ -27,7 +27,6 @@ final class DataBrokerProtectionFeatureGatekeeperTests: XCTestCase { private var sut: DefaultDataBrokerProtectionFeatureGatekeeper! private var mockFeatureDisabler: MockFeatureDisabler! private var mockFeatureAvailability: MockFeatureAvailability! - private var waitlistStorage: MockWaitlistStorage! private var mockAccountManager: MockAccountManager! private func userDefaults() -> UserDefaults { @@ -37,100 +36,15 @@ final class DataBrokerProtectionFeatureGatekeeperTests: XCTestCase { override func setUpWithError() throws { mockFeatureDisabler = MockFeatureDisabler() mockFeatureAvailability = MockFeatureAvailability() - waitlistStorage = MockWaitlistStorage() mockAccountManager = MockAccountManager() } - /// Waitlist is OFF, Not redeemed - /// PP flag is OF - func testWhenWaitlistHasNoInviteCodeAndFeatureDisabled_thenCleanUpIsNotCalled() throws { - sut = DefaultDataBrokerProtectionFeatureGatekeeper(featureDisabler: mockFeatureDisabler, - userDefaults: userDefaults(), - waitlistStorage: waitlistStorage, - subscriptionAvailability: mockFeatureAvailability, - accountManager: mockAccountManager) - - XCTAssertFalse(sut.cleanUpDBPForPrivacyProIfNecessary()) - XCTAssertFalse(mockFeatureDisabler.disableAndDeleteWasCalled) - } - - /// Waitlist is OFF, Not redeemed - /// PP flag is ON - func testWhenWaitlistHasNoInviteCodeAndFeatureEnabled_thenCleanUpIsNotCalled() throws { - mockFeatureAvailability.mockFeatureAvailable = true - - sut = DefaultDataBrokerProtectionFeatureGatekeeper(featureDisabler: mockFeatureDisabler, - userDefaults: userDefaults(), - waitlistStorage: waitlistStorage, - subscriptionAvailability: mockFeatureAvailability, - accountManager: mockAccountManager) - - XCTAssertFalse(sut.cleanUpDBPForPrivacyProIfNecessary()) - XCTAssertFalse(mockFeatureDisabler.disableAndDeleteWasCalled) - } - - /// Waitlist is ON, redeemed - /// PP flag is OFF - func testWhenWaitlistHasInviteCodeAndFeatureDisabled_thenCleanUpIsNotCalled() throws { - waitlistStorage.store(waitlistToken: "potato") - waitlistStorage.store(inviteCode: "banana") - waitlistStorage.store(waitlistTimestamp: 123) - - sut = DefaultDataBrokerProtectionFeatureGatekeeper(featureDisabler: mockFeatureDisabler, - userDefaults: userDefaults(), - waitlistStorage: waitlistStorage, - subscriptionAvailability: mockFeatureAvailability, - accountManager: mockAccountManager) - - XCTAssertFalse(sut.cleanUpDBPForPrivacyProIfNecessary()) - XCTAssertFalse(mockFeatureDisabler.disableAndDeleteWasCalled) - } - - /// Waitlist is ON, redeemed - /// PP flag is ON - func testWhenWaitlistHasInviteCodeAndFeatureEnabled_thenCleanUpIsCalled() throws { - waitlistStorage.store(waitlistToken: "potato") - waitlistStorage.store(inviteCode: "banana") - waitlistStorage.store(waitlistTimestamp: 123) - mockFeatureAvailability.mockFeatureAvailable = true - - sut = DefaultDataBrokerProtectionFeatureGatekeeper(featureDisabler: mockFeatureDisabler, - userDefaults: userDefaults(), - waitlistStorage: waitlistStorage, - subscriptionAvailability: mockFeatureAvailability, - accountManager: mockAccountManager) - - XCTAssertTrue(sut.cleanUpDBPForPrivacyProIfNecessary()) - XCTAssertTrue(mockFeatureDisabler.disableAndDeleteWasCalled) - } - - /// Waitlist is ON, redeemed - /// PP flag is ON - func testWhenWaitlistHasInviteCodeAndFeatureEnabled_thenCleanUpIsCalledTwice() throws { - waitlistStorage.store(waitlistToken: "potato") - waitlistStorage.store(inviteCode: "banana") - waitlistStorage.store(waitlistTimestamp: 123) - mockFeatureAvailability.mockFeatureAvailable = true - - sut = DefaultDataBrokerProtectionFeatureGatekeeper(featureDisabler: mockFeatureDisabler, - userDefaults: userDefaults(), - waitlistStorage: waitlistStorage, - subscriptionAvailability: mockFeatureAvailability, - accountManager: mockAccountManager) - - XCTAssertTrue(sut.cleanUpDBPForPrivacyProIfNecessary()) - XCTAssertTrue(mockFeatureDisabler.disableAndDeleteWasCalled) - - XCTAssertFalse(sut.cleanUpDBPForPrivacyProIfNecessary()) - } - func testWhenNoAccessTokenIsFound_butEntitlementIs_thenFeatureIsDisabled() async { // Given mockAccountManager.accessToken = nil mockAccountManager.hasEntitlementResult = .success(true) sut = DefaultDataBrokerProtectionFeatureGatekeeper(featureDisabler: mockFeatureDisabler, userDefaults: userDefaults(), - waitlistStorage: waitlistStorage, subscriptionAvailability: mockFeatureAvailability, accountManager: mockAccountManager) @@ -147,7 +61,6 @@ final class DataBrokerProtectionFeatureGatekeeperTests: XCTestCase { mockAccountManager.hasEntitlementResult = .failure(MockError.someError) sut = DefaultDataBrokerProtectionFeatureGatekeeper(featureDisabler: mockFeatureDisabler, userDefaults: userDefaults(), - waitlistStorage: waitlistStorage, subscriptionAvailability: mockFeatureAvailability, accountManager: mockAccountManager) @@ -164,7 +77,6 @@ final class DataBrokerProtectionFeatureGatekeeperTests: XCTestCase { mockAccountManager.hasEntitlementResult = .failure(MockError.someError) sut = DefaultDataBrokerProtectionFeatureGatekeeper(featureDisabler: mockFeatureDisabler, userDefaults: userDefaults(), - waitlistStorage: waitlistStorage, subscriptionAvailability: mockFeatureAvailability, accountManager: mockAccountManager) @@ -181,7 +93,6 @@ final class DataBrokerProtectionFeatureGatekeeperTests: XCTestCase { mockAccountManager.hasEntitlementResult = .success(true) sut = DefaultDataBrokerProtectionFeatureGatekeeper(featureDisabler: mockFeatureDisabler, userDefaults: userDefaults(), - waitlistStorage: waitlistStorage, subscriptionAvailability: mockFeatureAvailability, accountManager: mockAccountManager) From 1ad5031fb67c04dcce284dd49e6841176613609d Mon Sep 17 00:00:00 2001 From: Dax the Duck Date: Thu, 8 Aug 2024 05:17:26 +0000 Subject: [PATCH 30/32] Bump version to 1.101.0 (242) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index 2cfc7bd898a..cf30fe5f539 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 241 +CURRENT_PROJECT_VERSION = 242 From fee9032c61f28afb68c0eaa61fef434cf7a83351 Mon Sep 17 00:00:00 2001 From: Diego Rey Mendez Date: Wed, 7 Aug 2024 11:50:05 +0200 Subject: [PATCH 31/32] Pushes a tentative fix for the media permissions crash (#3075) Task/Issue URL: https://app.asana.com/0/1203108348835387/1207988315342624/f ## Description Tentative fix for media permissions crash. --- DuckDuckGo/Permissions/Model/PermissionModel.swift | 2 +- DuckDuckGo/Tab/Model/Tab+UIDelegate.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DuckDuckGo/Permissions/Model/PermissionModel.swift b/DuckDuckGo/Permissions/Model/PermissionModel.swift index 35bf07fe4f9..0bd5dc95e3a 100644 --- a/DuckDuckGo/Permissions/Model/PermissionModel.swift +++ b/DuckDuckGo/Permissions/Model/PermissionModel.swift @@ -226,7 +226,7 @@ final class PermissionModel { // MARK: - WebView delegated methods // Called before requestMediaCapturePermissionFor: to validate System Permissions - func checkUserMediaPermission(for url: URL, mainFrameURL: URL, decisionHandler: @escaping (String, Bool) -> Void) { + func checkUserMediaPermission(for url: URL?, mainFrameURL: URL?, decisionHandler: @escaping (String, Bool) -> Void) { // If media capture is denied in the System Preferences, reflect it in the current permissions // AVCaptureDevice.authorizationStatus(for:mediaType) is swizzled to determine requested media type // otherwise WebView won't call any other delegate methods if System Permission is denied diff --git a/DuckDuckGo/Tab/Model/Tab+UIDelegate.swift b/DuckDuckGo/Tab/Model/Tab+UIDelegate.swift index 81b12ca0b04..69b769e0658 100644 --- a/DuckDuckGo/Tab/Model/Tab+UIDelegate.swift +++ b/DuckDuckGo/Tab/Model/Tab+UIDelegate.swift @@ -176,11 +176,11 @@ extension Tab: WKUIDelegate, PrintingUserScriptDelegate { @objc(_webView:checkUserMediaPermissionForURL:mainFrameURL:frameIdentifier:decisionHandler:) func webView(_ webView: WKWebView, - checkUserMediaPermissionFor url: URL, - mainFrameURL: URL, + checkUserMediaPermissionFor url: NSURL?, + mainFrameURL: NSURL?, frameIdentifier: UInt64, decisionHandler: @escaping (String, Bool) -> Void) { - self.permissions.checkUserMediaPermission(for: url, mainFrameURL: mainFrameURL, decisionHandler: decisionHandler) + self.permissions.checkUserMediaPermission(for: url as? URL, mainFrameURL: mainFrameURL as? URL, decisionHandler: decisionHandler) } // https://github.com/WebKit/WebKit/blob/995f6b1595611c934e742a4f3a9af2e678bc6b8d/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegate.h#L147 From f299cd62344eee28b34f41b5269dc4ea03131d92 Mon Sep 17 00:00:00 2001 From: Dax the Duck Date: Fri, 9 Aug 2024 05:43:47 +0000 Subject: [PATCH 32/32] Bump version to 1.101.0 (243) --- Configuration/BuildNumber.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Configuration/BuildNumber.xcconfig b/Configuration/BuildNumber.xcconfig index cf30fe5f539..c2d20d19a60 100644 --- a/Configuration/BuildNumber.xcconfig +++ b/Configuration/BuildNumber.xcconfig @@ -1 +1 @@ -CURRENT_PROJECT_VERSION = 242 +CURRENT_PROJECT_VERSION = 243