diff --git a/Client/WebFilters/DebouncingResourceDownloader.swift b/Client/WebFilters/DebouncingResourceDownloader.swift index d94ffd5826b..62674135bc8 100644 --- a/Client/WebFilters/DebouncingResourceDownloader.swift +++ b/Client/WebFilters/DebouncingResourceDownloader.swift @@ -369,7 +369,8 @@ public class DebouncingResourceDownloader { } guard let extractedURL = try rule.extractRedirectURL(from: url), - url.host != extractedURL.host, + url.origin != extractedURL.origin, + url.baseDomain != extractedURL.baseDomain, extractedURL.scheme == "http" || extractedURL.scheme == "https" else { return nil } diff --git a/Tests/ClientTests/Resources/debouncing.json b/Tests/ClientTests/Resources/debouncing.json index ffed158aade..72aa384d2d5 100644 --- a/Tests/ClientTests/Resources/debouncing.json +++ b/Tests/ClientTests/Resources/debouncing.json @@ -244,6 +244,15 @@ "action": "regex-path", "param": "^/(.*)/(.*)$" }, + { + "include": [ + "http://a.click.example/bounce?url=*" + ], + "exclude": [ + ], + "action": "redirect", + "param": "url" + }, { "include": [ "*://brave-long-regex.example/*" diff --git a/Tests/ClientTests/Web Filters/DebouncingResourceDownloaderTests.swift b/Tests/ClientTests/Web Filters/DebouncingResourceDownloaderTests.swift index 6cebc9ce198..b42761b7337 100644 --- a/Tests/ClientTests/Web Filters/DebouncingResourceDownloaderTests.swift +++ b/Tests/ClientTests/Web Filters/DebouncingResourceDownloaderTests.swift @@ -110,7 +110,8 @@ class DebouncingResourceDownloaderTests: XCTestCase { let redirectChain = downloader.redirectChain(for: startURL) // Then - XCTAssertEqual(redirectChain.last?.url, finalURL) + // We stop at the intermediate URL because of same eTLD+1 restriction + XCTAssertEqual(redirectChain.last?.url, intermediateURL) } // Test a long redirect chain that bounces through the original URL's domain, @@ -374,6 +375,36 @@ class DebouncingResourceDownloaderTests: XCTestCase { ) } + /// Test several restrictions to debouncing + func testDebounceRestrictions() { + // Given + // A constructed url + let baseURL = URL(string: "https://a.click.example/bounce")! + let startURL1 = baseURL.addRedirectParam(URL(string: "https://a.click.example/dest")!) + let startURL2 = baseURL.addRedirectParam(URL(string: "https://b.click.example/dest")!) + let startURL3 = baseURL.addRedirectParam(URL(string: "ftp://b.click.example/dest")!) + + // When + // A redirect is returned + let redirectChain1 = downloader.redirectChain(for: startURL1) + let redirectChain2 = downloader.redirectChain(for: startURL2) + let redirectChain3 = downloader.redirectChain(for: startURL3) + + // Then + XCTAssertNil( + redirectChain1.last, + "This should be nil because origin matches" + ) + XCTAssertNil( + redirectChain2.last, + "This should be nil because eTLD+1 matches" + ) + XCTAssertNil( + redirectChain3.last, + "This should be nil because the schema is not http or https" + ) + } + /// Test regex rule where `prepend_scheme` is not specified and `base64` action is specified func testRegexRuleWithBase64DecodedURL() { // Given