diff --git a/DuckDuckGo/Autoconsent/AutoconsentUserScript.swift b/DuckDuckGo/Autoconsent/AutoconsentUserScript.swift index 97c1370bca..e48490cc23 100644 --- a/DuckDuckGo/Autoconsent/AutoconsentUserScript.swift +++ b/DuckDuckGo/Autoconsent/AutoconsentUserScript.swift @@ -195,6 +195,24 @@ extension AutoconsentUserScript { } } + func matchDomainList(domain: String?, domainsList: [String]) -> Bool { + guard let domain = domain else { return false } + let trimmedDomains = domainsList.filter { !$0.trimmingWhitespace().isEmpty } + + // Break domain apart to handle www.* + var tempDomain = domain + while tempDomain.contains(".") { + if trimmedDomains.contains(tempDomain) { + return true + } + + let comps = tempDomain.split(separator: ".") + tempDomain = comps.dropFirst().joined(separator: ".") + } + + return false + } + @MainActor func handleInit(message: WKScriptMessage, replyHandler: @escaping (Any?, String?) -> Void) { guard let messageData: InitMessage = decodeMessageBody(from: message.body), @@ -236,9 +254,10 @@ extension AutoconsentUserScript { } let remoteConfig = self.config.settings(for: .autoconsent) let disabledCMPs = remoteConfig["disabledCMPs"] as? [String] ?? [] - let enableFilterList = config.isSubfeatureEnabled(AutoconsentSubfeature.filterlist) + let filterlistExceptions = remoteConfig["filterlistExceptions"] as? [String] ?? [] + let enableFilterList = config.isSubfeatureEnabled(AutoconsentSubfeature.filterlist) && !self.matchDomainList(domain: topURLDomain, domainsList: filterlistExceptions) - replyHandler([ + let autoconsentConfig = [ "type": "initResp", "rules": nil, // rules are bundled with the content script atm "config": [ @@ -251,7 +270,10 @@ extension AutoconsentUserScript { "isMainWorld": false, "enableFilterList": enableFilterList ] as [String: Any?] - ] as [String: Any?], nil) + ] as [String: Any?] + Logger.autoconsent.debug("autoconsent config: \(String(describing: autoconsentConfig))") + + replyHandler(autoconsentConfig, nil) } @MainActor diff --git a/IntegrationTests/AutoconsentIntegrationTests.swift b/IntegrationTests/AutoconsentIntegrationTests.swift index ce5be346e4..aa5fef0b1a 100644 --- a/IntegrationTests/AutoconsentIntegrationTests.swift +++ b/IntegrationTests/AutoconsentIntegrationTests.swift @@ -173,6 +173,56 @@ class AutoconsentIntegrationTests: XCTestCase { XCTAssertTrue(isBannerHidden == true) } + @MainActor + func testFilterlistRule_whenFakeCookieBannerIsDisplayed_bannerIsHidden() async throws { + // enable the feature + CookiePopupProtectionPreferences.shared.isAutoconsentEnabled = true + let url = URL(string: "http://privacy-test-pages.site/features/autoconsent/filterlist.html")! + let tab = self.tabViewModel.tab + // expect `cosmetic` to be published + let cookieConsentManagedPromise = tab.privacyInfoPublisher + .compactMap { + return $0?.$cookieConsentManaged + } + .switchToLatest() + .compactMap { + return $0?.isCosmeticRuleApplied == true ? true : nil + } + .receive(on: DispatchQueue.main) + .timeout(10) + .first() + .promise() + + _=await tab.setUrl(url, source: .link)?.result + + do { + let cookieConsentManaged = try await cookieConsentManagedPromise.value + XCTAssertTrue(cookieConsentManaged == true) + } catch { + struct ErrorWithHTML: Error, LocalizedError, CustomDebugStringConvertible { + let originalError: Error + let html: String + + var errorDescription: String? { + (originalError as CustomDebugStringConvertible).debugDescription + "\nHTML:\n\(html)" + } + var debugDescription: String { + errorDescription! + } + } + let html = try await tab.webView.evaluateJavaScript("document.documentElement.outerHTML") as String? + + if let html { + throw ErrorWithHTML(originalError: error, html: html) + } else { + throw error + } + } + + let isBannerHidden = try await tab.webView.evaluateJavaScript("window.getComputedStyle(banner).opacity === '0'") as Bool? + XCTAssertTrue(isBannerHidden == true) + } + } private extension CookieConsentInfo {