Skip to content

Commit

Permalink
For third party requests differentiate if they are affiliated with fi…
Browse files Browse the repository at this point in the history
…rst party (#1003)

Please review the release process for BrowserServicesKit
[here](https://app.asana.com/0/1200194497630846/1200837094583426).

**Required**:

Task/Issue URL:
https://app.asana.com/0/414709148257752/1208376794617030/f
iOS PR: duckduckgo/iOS#3386
macOS PR: duckduckgo/macos-browser#3343
What kind of version bump will this require?: Minor

**Description**:
When loading a website and some of the allowed third party requests may
not be recognized as trackers but by their URL they may belong to the
same entity as the website. For that cases we should mark their state as
`.allowed(reason: .ownedByFirstParty)` (instead of `.allowed(reason:
.otherThirdPartyRequest)`).


**Steps to test this PR**:
See parent task for testing steps.

<!--
Before submitting a PR, please ensure you have tested the combinations
you expect the reviewer to test, then delete configurations you *know*
do not need explicit testing.

Using a simulator where a physical device is unavailable is acceptable.
-->

**OS Testing**:

* [ ] iOS 14
* [ ] iOS 15
* [ ] iOS 16
* [ ] macOS 10.15
* [ ] macOS 11
* [ ] macOS 12

---
###### Internal references:
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
  • Loading branch information
miasma13 authored Sep 27, 2024
1 parent 5b59c27 commit 20469bb
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
}
"""
Expand All @@ -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")!

Expand All @@ -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,
Expand Down Expand Up @@ -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<URL> = [websiteURL, self.nonTrackerURL]
let expected3rdParty: Set<String> = ["nontracker.com", "trackeraffiliated.com"]
let detected3rdParty = Set(self.userScriptDelegateMock.detectedThirdPartyRequests.map { $0.domain })
XCTAssertEqual(detected3rdParty, expected3rdParty)

let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand Down Expand Up @@ -216,11 +224,19 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase {
let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain })
XCTAssert(detectedTrackers.isEmpty)

let expected3rdParty: Set<String> = ["nontracker.com"]
let expected3rdParty: Set<String> = ["nontracker.com", "trackeraffiliated.com"]
let detected3rdParty = Set(self.userScriptDelegateMock.detectedThirdPartyRequests.map { $0.domain })
XCTAssertEqual(detected3rdParty, expected3rdParty)

let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL]
let expectedOwnedBy1stPartyRequests: Set<String> = ["trackeraffiliated.com"]
let detectedOwnedBy1stPartyRequests = Set(self.userScriptDelegateMock.detectedThirdPartyRequests.filter { $0.state == .allowed(reason: .ownedByFirstParty) }.map { $0.domain })
XCTAssertEqual(detectedOwnedBy1stPartyRequests, expectedOwnedBy1stPartyRequests)

let expectedOther3rdPartyRequests: Set<String> = ["nontracker.com"]
let detectedOther3rdPartyRequests = Set(self.userScriptDelegateMock.detectedThirdPartyRequests.filter { $0.state == .allowed(reason: .otherThirdPartyRequest) }.map { $0.domain })
XCTAssertEqual(detectedOther3rdPartyRequests, expectedOther3rdPartyRequests)

let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand All @@ -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<String> = ["trackeraffiliated.com"]
let detected3rdParty = Set(self.userScriptDelegateMock.detectedThirdPartyRequests.map { $0.domain })
XCTAssert(detected3rdParty.isEmpty)
XCTAssertEqual(detected3rdParty, expected3rdParty)

let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL]
let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand Down Expand Up @@ -280,7 +297,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase {
let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain })
XCTAssertEqual(expectedTrackers, detectedTrackers)

let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL]
let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand Down Expand Up @@ -312,7 +329,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase {
let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain })
XCTAssertEqual(expectedTrackers, detectedTrackers)

let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL]
let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand All @@ -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<URL> = [websiteURL, self.nonTrackerURL]
let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand All @@ -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<URL> = [websiteURL, self.nonTrackerURL]
let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand Down Expand Up @@ -396,7 +413,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase {
let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain })
XCTAssertEqual(expectedTrackers, detectedTrackers)

let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL]
let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand Down Expand Up @@ -426,7 +443,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase {
let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain })
XCTAssertEqual(expectedTrackers, detectedTrackers)

let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL]
let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand All @@ -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<URL> = [websiteURL, self.nonTrackerURL]
let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand Down Expand Up @@ -483,7 +500,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase {
let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain })
XCTAssertEqual(expectedTrackers, detectedTrackers)

let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL]
let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand Down Expand Up @@ -513,7 +530,7 @@ class ContentBlockerRulesUserScriptsTests: XCTestCase {
let detectedTrackers = Set(self.userScriptDelegateMock.detectedTrackers.map { $0.domain })
XCTAssertEqual(expectedTrackers, detectedTrackers)

let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.trackerURL, self.subTrackerURL]
let expectedRequests: Set<URL> = [websiteURL, self.nonTrackerURL, self.nonTrackerAffiliatedURL, self.trackerURL, self.subTrackerURL]
XCTAssertEqual(Set(self.schemeHandler.handledRequests), expectedRequests)
}

Expand Down

0 comments on commit 20469bb

Please sign in to comment.