773 lines · 34.6 KB · Swift
RawDownload
import Foundationimport os.lockimport Testing@testable import CodexBarCore #if os(macOS)import SweetCookieKit @Suite(.serialized)struct BrowserDetectionTests {    private func detection(        homeDirectory: String,        installedBrowsers: Set<Browser>) -> BrowserDetection    {        let installedAppPaths = Set(installedBrowsers.map { "/Applications/\($0.appBundleName).app" })        return BrowserDetection(            homeDirectory: homeDirectory,            cacheTTL: 0,            now: Date.init,            fileExists: { path in                if path.hasSuffix(".app") {                    return installedAppPaths.contains(path)                }                return FileManager.default.fileExists(atPath: path)            },            directoryContents: { path in                try? FileManager.default.contentsOfDirectory(atPath: path)            },            applicationURLs: { _ in [] },            profileAccessIssue: { _ in nil })    }     private static func labelIDs(for browser: Browser) -> [String] {        browser.safeStorageLabels.map { self.labelID(service: $0.service, account: $0.account) }    }     private static func labelID(service: String, account: String?) -> String {        "\(service)|\(account ?? "")"    }     @Test(.disabled(        if: ProcessInfo.processInfo.environment[BrowserCookieAccessGate.allowTestCookieAccessEnvironmentKey] == "1",        "Default-home cookie access is explicitly enabled for this test run."))    func `default home detection is suppressed before profile probes`() throws {        let probeCount = OSAllocatedUnfairLock(initialState: 0)        let defaultHome = try #require(BrowserCookieClient.defaultHomeDirectories().first)        let detection = BrowserDetection(            homeDirectory: defaultHome.path,            cacheTTL: 0,            fileExists: { _ in                probeCount.withLock { $0 += 1 }                return false            },            directoryContents: { _ in                probeCount.withLock { $0 += 1 }                return nil            })         _ = detection.isCookieSourceAvailable(.chrome)        #expect(probeCount.withLock { $0 } == 0)    }     @Test(.disabled(        if: ProcessInfo.processInfo.environment[BrowserCookieAccessGate.allowTestCookieAccessEnvironmentKey] == "1",        "Default-home cookie access is explicitly enabled for this test run."))    func `default client reports structured suppression before store discovery`() {        let client = BrowserCookieClient()         #expect(throws: BrowserCookieStoreAccessSuppressedError.self) {            _ = try client.codexBarStores(for: .chrome)        }        #expect(throws: BrowserCookieStoreAccessSuppressedError.self) {            _ = try client.codexBarRecords(                matching: BrowserCookieQuery(domains: ["example.com"]),                in: .safari)        }    }     @Test    func `cookie store decision allows production and explicit test opt in`() {        let defaultHomes = BrowserCookieClient.defaultHomeDirectories()        let testProcess = "swiftpm-testing-helper"         #expect(BrowserCookieAccessGate.cookieStoreAccessDecision(            homeDirectories: defaultHomes,            processName: testProcess,            environment: [:]) == .suppressed)        #expect(BrowserCookieAccessGate.cookieStoreAccessDecision(            homeDirectories: defaultHomes,            processName: testProcess,            environment: [BrowserCookieAccessGate.allowTestCookieAccessEnvironmentKey: "1"]) == .allowed)        #expect(BrowserCookieAccessGate.cookieStoreAccessDecision(            homeDirectories: defaultHomes,            processName: "CodexBar",            environment: [:]) == .allowed)    }     @Test(.disabled(        if: ProcessInfo.processInfo.environment[BrowserCookieAccessGate.allowTestCookieAccessEnvironmentKey] == "1",        "Default-home cookie access is explicitly enabled for this test run."))    func `safari is installed but default cookie access is disabled during tests`() {        #expect(BrowserDetection(cacheTTL: 0).isAppInstalled(.safari) == true)        #expect(BrowserDetection(cacheTTL: 0).isCookieSourceAvailable(.safari) == false)    }     @Test(.disabled(        if: ProcessInfo.processInfo.environment[BrowserCookieAccessGate.allowTestCookieAccessEnvironmentKey] == "1",        "Default-home cookie access is explicitly enabled for this test run."))    func `default cookie candidates exclude safari during tests`() {        let detection = BrowserDetection(cacheTTL: 0)        let browsers: [Browser] = [.safari, .chrome, .firefox]        #expect(browsers.cookieImportCandidates(using: detection).contains(.safari) == false)    }     @Test    func `explicit isolated home keeps safari cookie source available`() {        let detection = BrowserDetection(homeDirectory: "/tmp/codexbar-browser-detection", cacheTTL: 0)        #expect(detection.isCookieSourceAvailable(.safari))    }     @Test    func `cookie client permits isolated chromium stores during tests`() throws {        let temp = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)        let profile = temp            .appendingPathComponent("Library/Application Support/Google/Chrome/Default/Network")        try FileManager.default.createDirectory(at: profile, withIntermediateDirectories: true)        FileManager.default.createFile(atPath: profile.appendingPathComponent("Cookies").path, contents: Data())        defer { try? FileManager.default.removeItem(at: temp) }         let client = BrowserCookieClient(configuration: .init(homeDirectories: [temp]))        let stores = try KeychainAccessGate.withTaskOverrideForTesting(false) {            try KeychainAccessPreflight.withCheckGenericPasswordOverrideForTesting { _, _ in .allowed } operation: {                try ProviderInteractionContext.$current.withValue(.userInitiated) {                    try client.codexBarStores(for: .chrome)                }            }        }        #expect(stores.count == 1)    }     @Test    func `filter preserves order`() {        BrowserCookieAccessGate.resetForTesting()         let temp = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)        try? FileManager.default.createDirectory(at: temp, withIntermediateDirectories: true)        defer { try? FileManager.default.removeItem(at: temp) }         let firefoxProfile = temp            .appendingPathComponent("Library")            .appendingPathComponent("Application Support")            .appendingPathComponent("Firefox")            .appendingPathComponent("Profiles")            .appendingPathComponent("abc.default-release")        try? FileManager.default.createDirectory(at: firefoxProfile, withIntermediateDirectories: true)        FileManager.default.createFile(            atPath: firefoxProfile.appendingPathComponent("cookies.sqlite").path,            contents: Data())         let detection = self.detection(homeDirectory: temp.path, installedBrowsers: [.firefox])        let browsers: [Browser] = [.firefox, .safari, .chrome]        // Chrome is filtered out deterministically because it lacks usable on-disk profile/cookie store data.        #expect(browsers.cookieImportCandidates(using: detection) == [.firefox, .safari])    }     @Test    func `chrome requires profile data`() throws {        let temp = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)        try FileManager.default.createDirectory(at: temp, withIntermediateDirectories: true)        defer { try? FileManager.default.removeItem(at: temp) }         let detection = self.detection(homeDirectory: temp.path, installedBrowsers: [.chrome])        #expect(detection.isCookieSourceAvailable(.chrome) == false)         let profile = temp            .appendingPathComponent("Library")            .appendingPathComponent("Application Support")            .appendingPathComponent("Google")            .appendingPathComponent("Chrome")            .appendingPathComponent("Default")        try FileManager.default.createDirectory(at: profile, withIntermediateDirectories: true)        let cookiesDir = profile.appendingPathComponent("Network")        try FileManager.default.createDirectory(at: cookiesDir, withIntermediateDirectories: true)        FileManager.default.createFile(atPath: cookiesDir.appendingPathComponent("Cookies").path, contents: Data())         #expect(detection.isCookieSourceAvailable(.chrome) == true)    }     @Test    func `Vivaldi uses its Chromium profile and Safe Storage metadata`() throws {        let temp = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)        let profile = temp            .appendingPathComponent("Library")            .appendingPathComponent("Application Support")            .appendingPathComponent("Vivaldi")            .appendingPathComponent("Default")            .appendingPathComponent("Network")        try FileManager.default.createDirectory(at: profile, withIntermediateDirectories: true)        FileManager.default.createFile(atPath: profile.appendingPathComponent("Cookies").path, contents: Data())        defer { try? FileManager.default.removeItem(at: temp) }         let detection = self.detection(homeDirectory: temp.path, installedBrowsers: [.vivaldi])         #expect(Browser.vivaldi.chromiumProfileRelativePath == "Vivaldi")        #expect(Self.labelIDs(for: .vivaldi).contains("Vivaldi Safe Storage|Vivaldi"))        #expect(Browser.defaultImportOrder.contains(.vivaldi))        #expect(detection.isCookieSourceAvailable(.vivaldi))    }     @Test    func `process filters chromium candidates despite false global keychain override`() throws {        guard ProcessInfo.processInfo.environment["CODEXBAR_ALLOW_TEST_KEYCHAIN_ACCESS"] != "1" else { return }        KeychainAccessGate.resetOverrideForTesting()        defer { KeychainAccessGate.resetOverrideForTesting() }         KeychainAccessGate.isDisabled = false         let temp = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)        try FileManager.default.createDirectory(at: temp, withIntermediateDirectories: true)        defer { try? FileManager.default.removeItem(at: temp) }         let profile = temp            .appendingPathComponent("Library")            .appendingPathComponent("Application Support")            .appendingPathComponent("Google")            .appendingPathComponent("Chrome")            .appendingPathComponent("Default")        try FileManager.default.createDirectory(at: profile, withIntermediateDirectories: true)        let cookiesDir = profile.appendingPathComponent("Network")        try FileManager.default.createDirectory(at: cookiesDir, withIntermediateDirectories: true)        FileManager.default.createFile(atPath: cookiesDir.appendingPathComponent("Cookies").path, contents: Data())         let detection = self.detection(homeDirectory: temp.path, installedBrowsers: [.chrome])        let browsers: [Browser] = [.chrome, .safari]        #expect(browsers.cookieImportCandidates(using: detection) == [.safari])    }     @Test    func `keychain interaction suppresses chromium family during cooldown`() {        BrowserCookieAccessGate.resetForTesting()        defer { BrowserCookieAccessGate.resetForTesting() }         let start = Date(timeIntervalSince1970: 1000)        var preflightCount = 0         KeychainAccessGate.withTaskOverrideForTesting(false) {            ProviderInteractionContext.$current.withValue(.userInitiated) {                KeychainAccessPreflight.withCheckGenericPasswordOverrideForTesting { _, _ in                    preflightCount += 1                    return .interactionRequired                } operation: {                    #expect(BrowserCookieAccessGate.shouldAttempt(.chrome, now: start) == false)                }                 KeychainAccessPreflight.withCheckGenericPasswordOverrideForTesting { _, _ in                    preflightCount += 1                    return .allowed                } operation: {                    #expect(BrowserCookieAccessGate.shouldAttempt(.chrome, now: start.addingTimeInterval(60)) == false)                    #expect(BrowserCookieAccessGate.shouldAttempt(.dia, now: start.addingTimeInterval(60)) == false)                    #expect(                        BrowserCookieAccessGate.shouldAttempt(                            .chrome,                            now: start.addingTimeInterval((60 * 60 * 6) + 1)) == true)                }            }        }         #expect(preflightCount == 2)    }     @Test    func `background cookie import skips chromium before keychain preflight`() {        BrowserCookieAccessGate.resetForTesting()        defer { BrowserCookieAccessGate.resetForTesting() }         var preflightCount = 0         KeychainAccessGate.withTaskOverrideForTesting(false) {            KeychainAccessPreflight.withCheckGenericPasswordOverrideForTesting { _, _ in                preflightCount += 1                return .allowed            } operation: {                ProviderInteractionContext.$current.withValue(.background) {                    #expect(BrowserCookieAccessGate.shouldAttempt(.chrome) == false)                    #expect(BrowserCookieAccessGate.shouldAttempt(.safari) == true)                }            }        }         #expect(preflightCount == 0)    }     @Test    func `background cookie import skips chromium without probing keychain interaction`() {        BrowserCookieAccessGate.resetForTesting()        defer { BrowserCookieAccessGate.resetForTesting() }         var preflightCount = 0         KeychainAccessGate.withTaskOverrideForTesting(false) {            KeychainAccessPreflight.withCheckGenericPasswordOverrideForTesting { _, _ in                preflightCount += 1                return .interactionRequired            } operation: {                ProviderInteractionContext.$current.withValue(.background) {                    #expect(BrowserCookieAccessGate.shouldAttempt(.chrome) == false)                    #expect(BrowserCookieAccessGate.shouldAttempt(.safari) == true)                }            }        }         #expect(preflightCount == 0)    }     @Test    func `recorded browser denial suppresses automatic family and permits explicit source retry`() {        BrowserCookieAccessGate.resetForTesting()        defer { BrowserCookieAccessGate.resetForTesting() }         let start = Date(timeIntervalSince1970: 1500)        var preflightCount = 0         KeychainAccessGate.withTaskOverrideForTesting(false) {            BrowserCookieAccessGate.recordIfNeeded(                BrowserCookieError.accessDenied(browser: .arc, details: "denied"),                now: start)            KeychainAccessPreflight.withCheckGenericPasswordOverrideForTesting { _, _ in                preflightCount += 1                return .allowed            } operation: {                ProviderInteractionContext.$current.withValue(.background) {                    #expect(BrowserCookieAccessGate.shouldAttempt(.chrome, now: start.addingTimeInterval(1)) == false)                    #expect(BrowserCookieAccessGate.shouldAttempt(.edge, now: start.addingTimeInterval(1)) == false)                    #expect(BrowserCookieAccessGate.shouldAttempt(.safari, now: start.addingTimeInterval(1)) == true)                }                BrowserCookieAccessGate.withExplicitRetry {                    ProviderInteractionContext.$current.withValue(.userInitiated) {                        #expect(BrowserCookieAccessGate                            .shouldAttempt(.chrome, now: start.addingTimeInterval(2)) == false)                        #expect(BrowserCookieAccessGate.shouldAttempt(.arc, now: start.addingTimeInterval(2)) == true)                        #expect(BrowserCookieAccessGate.claimExplicitRetryCookieReadIfNeeded(for: .arc))                        BrowserCookieAccessGate.recordAllowed(for: .arc)                    }                }                ProviderInteractionContext.$current.withValue(.userInitiated) {                    #expect(BrowserCookieAccessGate.shouldAttempt(.chrome, now: start.addingTimeInterval(3)) == true)                }            }        }         #expect(preflightCount == 2)    }     @Test    func `denied explicit cookie read closes retry scope`() {        BrowserCookieAccessGate.resetForTesting()        defer { BrowserCookieAccessGate.resetForTesting() }         let start = Date(timeIntervalSince1970: 1700)        BrowserCookieAccessGate.recordDenied(for: .arc, now: start)         KeychainAccessGate.withTaskOverrideForTesting(false) {            BrowserCookieAccessGate.withExplicitRetry {                ProviderInteractionContext.$current.withValue(.userInitiated) {                    #expect(BrowserCookieAccessGate.shouldAttempt(.arc, now: start.addingTimeInterval(1)))                    #expect(BrowserCookieAccessGate.claimExplicitRetryCookieReadIfNeeded(for: .arc))                     BrowserCookieAccessGate.recordDenied(for: .arc, now: start.addingTimeInterval(2))                     #expect(BrowserCookieAccessGate.shouldAttempt(.arc, now: start.addingTimeInterval(3)) == false)                    #expect(BrowserCookieAccessGate.shouldAttempt(.edge, now: start.addingTimeInterval(3)) == false)                }            }        }    }     @Test    func `chrome keychain preflight queries only chrome labels`() {        BrowserCookieAccessGate.resetForTesting()        defer { BrowserCookieAccessGate.resetForTesting() }         let chromeLabels = Self.labelIDs(for: .chrome)        let chromeLabelSet = Set(chromeLabels)        var queriedLabels: [String] = []         KeychainAccessGate.withTaskOverrideForTesting(false) {            KeychainAccessPreflight.withCheckGenericPasswordOverrideForTesting { service, account in                let label = Self.labelID(service: service, account: account)                queriedLabels.append(label)                return .notFound            } operation: {                ProviderInteractionContext.$current.withValue(.userInitiated) {                    #expect(BrowserCookieAccessGate.shouldAttempt(.chrome) == true)                }            }        }         #expect(queriedLabels == chromeLabels)        #expect(queriedLabels.allSatisfy { chromeLabelSet.contains($0) })    }     @Test    func `dia keychain preflight queries only dia labels`() {        BrowserCookieAccessGate.resetForTesting()        defer { BrowserCookieAccessGate.resetForTesting() }         let diaLabels = Self.labelIDs(for: .dia)        let diaLabelSet = Set(diaLabels)        var queriedLabels: [String] = []         KeychainAccessGate.withTaskOverrideForTesting(false) {            KeychainAccessPreflight.withCheckGenericPasswordOverrideForTesting { service, account in                let label = Self.labelID(service: service, account: account)                queriedLabels.append(label)                return .notFound            } operation: {                ProviderInteractionContext.$current.withValue(.userInitiated) {                    #expect(BrowserCookieAccessGate.shouldAttempt(.dia) == true)                }            }        }         #expect(queriedLabels == diaLabels)        #expect(queriedLabels.allSatisfy { diaLabelSet.contains($0) })    }     @Test    func `browser keychain interaction suppresses family and permits scoped explicit retry`() throws {        BrowserCookieAccessGate.resetForTesting()        defer { BrowserCookieAccessGate.resetForTesting() }         let start = Date(timeIntervalSince1970: 2000)        let chromeLabels = Self.labelIDs(for: .chrome)        let diaLabels = Self.labelIDs(for: .dia)        let firstChromeLabel = try #require(chromeLabels.first)        let firstDiaLabel = try #require(diaLabels.first)        let allowedLabels = Set(chromeLabels + diaLabels)        var queriedLabels: [String] = []         KeychainAccessGate.withTaskOverrideForTesting(false) {            KeychainAccessPreflight.withCheckGenericPasswordOverrideForTesting { service, account in                let label = Self.labelID(service: service, account: account)                queriedLabels.append(label)                if label == firstChromeLabel {                    return .allowed                }                if label == firstDiaLabel {                    return .interactionRequired                }                return .notFound            } operation: {                ProviderInteractionContext.$current.withValue(.userInitiated) {                    #expect(BrowserCookieAccessGate.shouldAttempt(.chrome, now: start) == true)                    #expect(BrowserCookieAccessGate.shouldAttempt(.dia, now: start.addingTimeInterval(1)) == false)                    #expect(BrowserCookieAccessGate.shouldAttempt(.chrome, now: start.addingTimeInterval(60)) == false)                    #expect(BrowserCookieAccessGate.shouldAttempt(.dia, now: start.addingTimeInterval(60)) == false)                }                BrowserCookieAccessGate.withExplicitRetry {                    ProviderInteractionContext.$current.withValue(.userInitiated) {                        #expect(BrowserCookieAccessGate                            .shouldAttempt(.chrome, now: start.addingTimeInterval(61)) == false)                        #expect(BrowserCookieAccessGate.shouldAttempt(.dia, now: start.addingTimeInterval(61)) == true)                        #expect(BrowserCookieAccessGate                            .shouldAttempt(.edge, now: start.addingTimeInterval(61)) == false)                    }                }            }        }         #expect(queriedLabels == [firstChromeLabel, firstDiaLabel, firstDiaLabel])        #expect(queriedLabels.allSatisfy { allowedLabels.contains($0) })    }     @Test    func `dia requires profile data`() throws {        let temp = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)        try FileManager.default.createDirectory(at: temp, withIntermediateDirectories: true)        defer { try? FileManager.default.removeItem(at: temp) }         let detection = self.detection(homeDirectory: temp.path, installedBrowsers: [.dia])        #expect(detection.isCookieSourceAvailable(.dia) == false)         let profile = temp            .appendingPathComponent("Library")            .appendingPathComponent("Application Support")            .appendingPathComponent("Dia")            .appendingPathComponent("User Data")            .appendingPathComponent("Default")        try FileManager.default.createDirectory(at: profile, withIntermediateDirectories: true)        let cookiesDir = profile.appendingPathComponent("Network")        try FileManager.default.createDirectory(at: cookiesDir, withIntermediateDirectories: true)        FileManager.default.createFile(atPath: cookiesDir.appendingPathComponent("Cookies").path, contents: Data())         #expect(detection.isCookieSourceAvailable(.dia) == true)    }     @Test    func `removed browser with stale cookies is not a candidate`() throws {        let temp = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)

Lines 1–500 of 773.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t