diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 5166d45..d4d9155 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -63,6 +63,7 @@ body: - Brave - Vivaldi - Firefox (experimental) + - ChatGPT Atlas validations: required: false diff --git a/README.md b/README.md index 810e73c..b98e7a6 100644 --- a/README.md +++ b/README.md @@ -83,7 +83,7 @@ SimplyTrack requires several macOS permissions to function properly: 1. **Automation Permission**: To track browser activity - System Preferences → Privacy & Security → Automation - - Enable SimplyTrack for your browsers (Safari, Chrome, Edge, Arc, Brave, Vivaldi, Firefox) + - Enable SimplyTrack for your browsers (Safari, Chrome, Edge, Arc, Brave, Vivaldi, Firefox, ChatGPT Atlas) 2. **System Events Permission**: For Safari and Firefox browser integration - System Preferences → Privacy & Security → Automation diff --git a/SimplyTrack/Managers/PermissionManager.swift b/SimplyTrack/Managers/PermissionManager.swift index 0e8b388..540137a 100644 --- a/SimplyTrack/Managers/PermissionManager.swift +++ b/SimplyTrack/Managers/PermissionManager.swift @@ -44,6 +44,8 @@ class PermissionManager: ObservableObject { "com.brave.Browser", "com.vivaldi.Vivaldi", "org.mozilla.firefox", + "com.openai.atlas", + "com.openai.atlas.web", ] private init() { diff --git a/SimplyTrack/Services/Browsers/AtlasBrowser.swift b/SimplyTrack/Services/Browsers/AtlasBrowser.swift new file mode 100644 index 0000000..a48bf34 --- /dev/null +++ b/SimplyTrack/Services/Browsers/AtlasBrowser.swift @@ -0,0 +1,55 @@ +// +// AtlasBrowser.swift +// SimplyTrack +// + +import Foundation + +/// ChatGPT Atlas-specific implementation of browser interface. +/// Handles URL detection and incognito mode detection for ChatGPT Atlas. +/// Atlas is Chromium-based and shares the same AppleScript interface as Chrome. +class AtlasBrowser: BaseBrowser { + static let appBundleId = "com.openai.atlas" + static let webBundleId = "com.openai.atlas.web" + static let supportedBundleIds = [appBundleId, webBundleId] + + init() { + super.init(bundleId: Self.appBundleId, displayName: "ChatGPT Atlas") + } + + /// ChatGPT Atlas-specific AppleScript for URL retrieval + override var currentURLScript: String { + return """ + tell application id "\(Self.webBundleId)" + if (count of windows) > 0 then + set currentTab to active tab of window 1 + return URL of currentTab + end if + end tell + """ + } + + /// Checks if ChatGPT Atlas is currently in incognito mode. + /// Uses the 'mode' property available in Atlas's Chromium AppleScript interface. + /// Note: Permissions are already verified by getCurrentURL() call, so no need to re-check. + /// - Returns: true if incognito mode is detected, false otherwise + override func isInPrivateBrowsingMode() -> Bool { + let script = """ + tell application id "\(Self.webBundleId)" + if (count of windows) > 0 then + return mode of window 1 is equal to "incognito" + end if + end tell + """ + + let scriptResult = executeAppleScript(script) + + guard let result = scriptResult.result, + let isIncognito = Bool(result.lowercased()) + else { + return false + } + + return isIncognito + } +} diff --git a/SimplyTrack/Services/WebTrackingService.swift b/SimplyTrack/Services/WebTrackingService.swift index 19418ef..baaed62 100644 --- a/SimplyTrack/Services/WebTrackingService.swift +++ b/SimplyTrack/Services/WebTrackingService.swift @@ -3,7 +3,7 @@ // SimplyTrack // // Handles browser integration, AppleScript execution, favicon fetching, and website detection -// Supports Safari, Chrome, Edge, Arc, Brave, Vivaldi, and Firefox through AppleScript communication for website tracking +// Supports Safari, Chrome, Edge, Arc, Brave, Vivaldi, Firefox, and ChatGPT Atlas through AppleScript communication for website tracking // import AppKit @@ -56,17 +56,27 @@ actor FaviconCacheActor { class WebTrackingService { - private let browsers: [String: BrowserInterface] = [ - SafariBrowser(), - ChromeBrowser(), - EdgeBrowser(), - ArcBrowser(), - BraveBrowser(), - VivaldiBrowser(), - FirefoxBrowser(), - ].reduce(into: [:]) { result, browser in - result[browser.bundleId] = browser - } + private let browsers: [String: BrowserInterface] = { + let atlasBrowser = AtlasBrowser() + var browsers = [ + SafariBrowser(), + ChromeBrowser(), + EdgeBrowser(), + ArcBrowser(), + BraveBrowser(), + VivaldiBrowser(), + FirefoxBrowser(), + atlasBrowser, + ].reduce(into: [String: BrowserInterface]()) { result, browser in + result[browser.bundleId] = browser + } + + for bundleId in AtlasBrowser.supportedBundleIds { + browsers[bundleId] = atlasBrowser + } + + return browsers + }() private let faviconCacheActor = FaviconCacheActor() diff --git a/SimplyTrack/SimplyTrack.entitlements b/SimplyTrack/SimplyTrack.entitlements index f0da4f8..658a08c 100644 --- a/SimplyTrack/SimplyTrack.entitlements +++ b/SimplyTrack/SimplyTrack.entitlements @@ -13,6 +13,8 @@ com.brave.Browser com.vivaldi.Vivaldi org.mozilla.firefox + com.openai.atlas + com.openai.atlas.web com.apple.systemevents com.apple.security.temporary-exception.files.home-relative-path.read-only diff --git a/SimplyTrackTests/BrowserSupportTests.swift b/SimplyTrackTests/BrowserSupportTests.swift new file mode 100644 index 0000000..234eb46 --- /dev/null +++ b/SimplyTrackTests/BrowserSupportTests.swift @@ -0,0 +1,32 @@ +// +// BrowserSupportTests.swift +// SimplyTrackTests +// +// Created by Hermes Agent on 06.05.2026. +// + +import Testing + +@testable import SimplyTrack + +struct BrowserSupportTests { + + @Test func chatGPTAtlasIsRecognizedAsSupportedBrowser() { + let service = WebTrackingService() + + let browser = service.getBrowser(for: "com.openai.atlas") + + #expect(browser != nil) + #expect(browser?.bundleId == "com.openai.atlas") + } + + @Test func chatGPTAtlasWebProcessIsRecognizedAsSupportedBrowser() { + let service = WebTrackingService() + + let browser = service.getBrowser(for: "com.openai.atlas.web") + + #expect(browser != nil) + #expect(browser?.bundleId == "com.openai.atlas") + #expect(browser?.displayName == "ChatGPT Atlas") + } +}