diff --git a/Sources/BrowserServicesKit/ContentBlocking/UserScripts/ContentBlockerRulesUserScript.swift b/Sources/BrowserServicesKit/ContentBlocking/UserScripts/ContentBlockerRulesUserScript.swift index ad2bc44e8..0278ed64e 100644 --- a/Sources/BrowserServicesKit/ContentBlocking/UserScripts/ContentBlockerRulesUserScript.swift +++ b/Sources/BrowserServicesKit/ContentBlocking/UserScripts/ContentBlockerRulesUserScript.swift @@ -187,11 +187,13 @@ open class ContentBlockerRulesUserScript: NSObject, UserScript { !isFirstParty(requestURL: trackerUrlString, websiteURL: pageUrlStr) else { return } let entity = currentTrackerData.findEntity(forHost: requestETLDp1) ?? Entity(displayName: requestETLDp1, domains: nil, prevalence: nil) + let isAffiliated = resolver.isPageAffiliatedWithTrackerEntity(pageUrlString: pageUrlStr, trackerEntity: entity) + let thirdPartyRequest = DetectedRequest(url: trackerUrlString, eTLDplus1: requestETLDp1, knownTracker: nil, entity: entity, - state: .allowed(reason: .otherThirdPartyRequest), + state: .allowed(reason: isAffiliated ? .ownedByFirstParty : .otherThirdPartyRequest), pageUrl: pageUrlStr) delegate.contentBlockerRulesUserScript(self, detectedThirdPartyRequest: thirdPartyRequest) } diff --git a/Sources/BrowserServicesKit/ContentBlocking/UserScripts/TrackerResolver.swift b/Sources/BrowserServicesKit/ContentBlocking/UserScripts/TrackerResolver.swift index 8e1b2baae..36a5974d7 100644 --- a/Sources/BrowserServicesKit/ContentBlocking/UserScripts/TrackerResolver.swift +++ b/Sources/BrowserServicesKit/ContentBlocking/UserScripts/TrackerResolver.swift @@ -85,7 +85,7 @@ public class TrackerResolver { pageUrl: pageUrlString) } - private func isPageAffiliatedWithTrackerEntity(pageUrlString: String, trackerEntity: Entity) -> Bool { + public func isPageAffiliatedWithTrackerEntity(pageUrlString: String, trackerEntity: Entity) -> Bool { guard let pageHost = URL(string: pageUrlString)?.host, let pageEntity = tds.findEntity(forHost: pageHost) else { return false } diff --git a/Tests/BrowserServicesKitTests/ContentBlocker/ContentBlockerRulesUserScriptsTests.swift b/Tests/BrowserServicesKitTests/ContentBlocker/ContentBlockerRulesUserScriptsTests.swift index f6b4440e5..8d48a1ff4 100644 --- a/Tests/BrowserServicesKitTests/ContentBlocker/ContentBlockerRulesUserScriptsTests.swift +++ b/Tests/BrowserServicesKitTests/ContentBlocker/ContentBlockerRulesUserScriptsTests.swift @@ -59,14 +59,16 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { "entities": { "Fake Tracking Inc": { "domains": [ - "tracker.com" + "tracker.com", + "trackeraffiliated.com" ], "displayName": "Fake Tracking Inc", "prevalence": 0.1 } }, "domains": { - "tracker.com": "Fake Tracking Inc" + "tracker.com": "Fake Tracking Inc", + "trackeraffiliated.com": "Fake Tracking Inc" } } """ @@ -79,6 +81,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { var webView: WKWebView? let nonTrackerURL = URL(string: "test://nontracker.com/1.png")! + let nonTrackerAffiliatedURL = URL(string: "test://trackeraffiliated.com/1.png")! let trackerURL = URL(string: "test://tracker.com/1.png")! let subTrackerURL = URL(string: "test://sub.tracker.com/1.png")! @@ -89,7 +92,8 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { website = MockWebsite(resources: [.init(type: .image, url: nonTrackerURL), .init(type: .image, url: trackerURL), - .init(type: .image, url: subTrackerURL)]) + .init(type: .image, url: subTrackerURL), + .init(type: .image, url: nonTrackerAffiliatedURL)]) } private func setupWebViewForUserScripTests(trackerData: TrackerData, @@ -186,7 +190,11 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let blockedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.filter { $0.isBlocked }.map { $0.domain }) XCTAssertEqual(expectedTrackers, blockedTrackers) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL] + let expected3rdParty: Set = ["nontracker.com", "trackeraffiliated.com"] + let detected3rdParty = Set(self.userScriptDelegateMock.detectedThirdPartyRequests.map { $0.domain }) + XCTAssertEqual(detected3rdParty, expected3rdParty) + + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) } @@ -216,11 +224,19 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain }) XCTAssert(detectedTrackers.isEmpty) - let expected3rdParty: Set = ["nontracker.com"] + let expected3rdParty: Set = ["nontracker.com", "trackeraffiliated.com"] let detected3rdParty = Set(self.userScriptDelegateMock.detectedThirdPartyRequests.map { $0.domain }) XCTAssertEqual(detected3rdParty, expected3rdParty) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL] + let expectedOwnedBy1stPartyRequests: Set = ["trackeraffiliated.com"] + let detectedOwnedBy1stPartyRequests = Set(self.userScriptDelegateMock.detectedThirdPartyRequests.filter { $0.state == .allowed(reason: .ownedByFirstParty) }.map { $0.domain }) + XCTAssertEqual(detectedOwnedBy1stPartyRequests, expectedOwnedBy1stPartyRequests) + + let expectedOther3rdPartyRequests: Set = ["nontracker.com"] + let detectedOther3rdPartyRequests = Set(self.userScriptDelegateMock.detectedThirdPartyRequests.filter { $0.state == .allowed(reason: .otherThirdPartyRequest) }.map { $0.domain }) + XCTAssertEqual(detectedOther3rdPartyRequests, expectedOther3rdPartyRequests) + + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) } @@ -247,10 +263,11 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let blockedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.filter { $0.isBlocked }.map { $0.domain }) XCTAssertEqual(blockedTrackers, expectedTrackers) + let expected3rdParty: Set = ["trackeraffiliated.com"] let detected3rdParty = Set(self.userScriptDelegateMock.detectedThirdPartyRequests.map { $0.domain }) - XCTAssert(detected3rdParty.isEmpty) + XCTAssertEqual(detected3rdParty, expected3rdParty) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL] + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) } @@ -280,7 +297,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain }) XCTAssertEqual(expectedTrackers, detectedTrackers) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL] + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) } @@ -312,7 +329,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain }) XCTAssertEqual(expectedTrackers, detectedTrackers) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL] + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) } @@ -339,7 +356,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let blockedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.filter { $0.isBlocked }.map { $0.domain }) XCTAssertEqual(expectedTrackers, blockedTrackers) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL] + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) } @@ -366,7 +383,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let blockedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.filter { $0.isBlocked }.map { $0.domain }) XCTAssertEqual(expectedTrackers, blockedTrackers) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL] + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) } @@ -396,7 +413,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain }) XCTAssertEqual(expectedTrackers, detectedTrackers) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL] + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) } @@ -426,7 +443,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain }) XCTAssertEqual(expectedTrackers, detectedTrackers) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL] + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) } @@ -453,7 +470,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let blockedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.filter { $0.isBlocked }.map { $0.domain }) XCTAssertEqual(expectedTrackers, blockedTrackers) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL] + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) } @@ -483,7 +500,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain }) XCTAssertEqual(expectedTrackers, detectedTrackers) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL] + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) } @@ -513,7 +530,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase { let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain }) XCTAssertEqual(expectedTrackers, detectedTrackers) - let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL] + let expectedRequests: Set = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL] XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests) }