Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ All notable changes to cmux are documented here.
- iOS (beta): collapse workspace folders per device ([#6666](https://github.com/manaflow-ai/cmux/pull/6666))

### Fixed
- Open Settings > Account sign-in in the user's default browser instead of the Safari-backed auth sheet.
- Fix a sidebar lag regression from v0.64.16 by cutting per-row font-modifier and pin-state work ([#6613](https://github.com/manaflow-ai/cmux/pull/6613))
- Fix the Codex sidebar status lifecycle and stale Claude notification sidebar status ([#6609](https://github.com/manaflow-ai/cmux/pull/6609), [#6473](https://github.com/manaflow-ai/cmux/pull/6473))
- Fix sidebar tab selection highlight timing ([#6627](https://github.com/manaflow-ai/cmux/pull/6627))
Expand Down
13 changes: 0 additions & 13 deletions Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,6 @@
<string>A program running within cmux would like to use AppleScript.</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>CFBundleURLName</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).web</string>
<key>LSHandlerRank</key>
<string>Default</string>
<key>CFBundleURLSchemes</key>
<array>
<string>http</string>
<string>https</string>
</array>
</dict>
<dict>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
Expand Down
41 changes: 41 additions & 0 deletions Sources/Auth/DefaultBrowserAuthSessionFactory.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import AppKit
import CmuxAuthRuntime
import Foundation

/// Opens hosted sign-in in the user's default browser.
@MainActor
final class DefaultBrowserAuthSessionFactory: HostBrowserAuthSessionFactory {
private let opener: @MainActor (URL) -> Bool

init(opener: @escaping @MainActor (URL) -> Bool = { NSWorkspace.shared.open($0) }) {
self.opener = opener
}

func makeSession(
signInURL: URL,
callbackScheme _: String,
completion _: @escaping @MainActor (HostBrowserAuthSessionResult) -> Void
) -> any HostBrowserAuthSession {
DefaultBrowserAuthSession(signInURL: signInURL, opener: opener)
}
}

@MainActor
private final class DefaultBrowserAuthSession: HostBrowserAuthSession {
private let signInURL: URL
private let opener: @MainActor (URL) -> Bool

init(signInURL: URL, opener: @escaping @MainActor (URL) -> Bool) {
self.signInURL = signInURL
self.opener = opener
}

func start() -> Bool {
opener(signInURL)
}

func cancel() {
// NSWorkspace opens the user's browser as a separate app; there is no
// owned AuthenticationServices session for cmux to cancel.
}
}
2 changes: 1 addition & 1 deletion Sources/Auth/MacAuthComposition.swift
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ struct MacAuthComposition {
self.browserSignIn = HostBrowserSignInFlow(
coordinator: coordinator,
tokenStore: tokenStore,
sessionFactory: ASWebBrowserAuthSessionFactory(anchor: anchor),
sessionFactory: DefaultBrowserAuthSessionFactory(),
callbackRouter: callbackRouter,
makeSignInURL: { AuthEnvironment.signInURL(callbackState: $0) },
callbackScheme: { AuthEnvironment.callbackScheme }
Expand Down
8 changes: 8 additions & 0 deletions cmux.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,8 @@
DEBDADADADADADADAD000001 /* DebugDogfoodCredentialResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEBDADADADADADADAD000002 /* DebugDogfoodCredentialResolver.swift */; };
DEBDADADADADADADAD000003 /* DebugDogfoodCredentialResolverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DEBDADADADADADADAD000004 /* DebugDogfoodCredentialResolverTests.swift */; };
A500D010A1B2C3D4E5F60718 /* DebugLogging.swift in Sources */ = {isa = PBXBuildFile; fileRef = A500D011A1B2C3D4E5F60718 /* DebugLogging.swift */; };
E36170000000000000000001 /* DefaultBrowserAuthSessionFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36170000000000000000002 /* DefaultBrowserAuthSessionFactory.swift */; };
E36170000000000000000003 /* DefaultBrowserAuthSessionFactoryTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E36170000000000000000004 /* DefaultBrowserAuthSessionFactoryTests.swift */; };
A5001F000000000000000001 /* DetachedFolderDragIcon.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001F000000000000000002 /* DetachedFolderDragIcon.swift */; };
B05553C10000000000000001 /* DetachedFolderPathLookupCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = B05553C10000000000000002 /* DetachedFolderPathLookupCache.swift */; };
B0555303B0555303B0555303 /* DetachedFolderPathLookupCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0555304B0555304B0555304 /* DetachedFolderPathLookupCacheTests.swift */; };
Expand Down Expand Up @@ -1448,6 +1450,8 @@
DEBDADADADADADADAD000002 /* DebugDogfoodCredentialResolver.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DebugDogfoodCredentialResolver.swift; sourceTree = "<group>"; };
DEBDADADADADADADAD000004 /* DebugDogfoodCredentialResolverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugDogfoodCredentialResolverTests.swift; sourceTree = "<group>"; };
A500D011A1B2C3D4E5F60718 /* DebugLogging.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App/DebugLogging.swift; sourceTree = "<group>"; };
E36170000000000000000002 /* DefaultBrowserAuthSessionFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultBrowserAuthSessionFactory.swift; sourceTree = "<group>"; };
E36170000000000000000004 /* DefaultBrowserAuthSessionFactoryTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultBrowserAuthSessionFactoryTests.swift; sourceTree = "<group>"; };
A5001F000000000000000002 /* DetachedFolderDragIcon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetachedFolderDragIcon.swift; sourceTree = "<group>"; };
B05553C10000000000000002 /* DetachedFolderPathLookupCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetachedFolderPathLookupCache.swift; sourceTree = "<group>"; };
B0555304B0555304B0555304 /* DetachedFolderPathLookupCacheTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetachedFolderPathLookupCacheTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2256,6 +2260,7 @@
isa = PBXGroup;
children = (
43430FA5929121E2EAAB3091 /* AuthEnvironment.swift */,
E36170000000000000000002 /* DefaultBrowserAuthSessionFactory.swift */,
DEBDADADADADADADAD000002 /* DebugDogfoodCredentialResolver.swift */,
53750023A0B1C2D3E4F50023 /* MacAuthComposition.swift */,
CD0CFE6100000000CD0CFE61 /* HostAccountFlow.swift */,
Expand Down Expand Up @@ -3046,6 +3051,7 @@
BCBC0A0E0000000000000D02 /* BrowserChromeMetricsTests.swift */,
BCBC0A0E0000000000000E12 /* BrowserMediaActivityAggregationTests.swift */,
BCBC0A0E0000000000000E22 /* BrowserMediaPlaybackAudioActivityTests.swift */,
E36170000000000000000004 /* DefaultBrowserAuthSessionFactoryTests.swift */,
A11EB0000000000000000001 /* GhosttyConfigPathResolverTests.swift */,
C13519000000000000000004 /* GhosttyTerminalStartupEnvironmentTests.swift */,
C13519000000000000000008 /* ClaudeConfigDirectoryPathTests.swift */,
Expand Down Expand Up @@ -3905,6 +3911,7 @@
C57B00090000000000000001 /* CustomSidebarPanelView.swift in Sources */,
DEBDADADADADADADAD000001 /* DebugDogfoodCredentialResolver.swift in Sources */,
A500D010A1B2C3D4E5F60718 /* DebugLogging.swift in Sources */,
E36170000000000000000001 /* DefaultBrowserAuthSessionFactory.swift in Sources */,
A5001F000000000000000001 /* DetachedFolderDragIcon.swift in Sources */,
B05553C10000000000000001 /* DetachedFolderPathLookupCache.swift in Sources */,
DE71CE000000000000000004 /* DeviceRegistryClient.swift in Sources */,
Expand Down Expand Up @@ -4552,6 +4559,7 @@
C1713006C1713006C1713006 /* CommandPaletteShortcutCustomizationTests.swift in Sources */,
C65930010000000000000002 /* CrashDiagnosticSessionPolicyTests.swift in Sources */,
DEBDADADADADADADAD000003 /* DebugDogfoodCredentialResolverTests.swift in Sources */,
E36170000000000000000003 /* DefaultBrowserAuthSessionFactoryTests.swift in Sources */,
B0555303B0555303B0555303 /* DetachedFolderPathLookupCacheTests.swift in Sources */,
DE71CE000000000000000002 /* DeviceRegistryClientTests.swift in Sources */,
D1FFC0DE000000000000C002 /* DiffCommentStoreTests.swift in Sources */,
Expand Down
47 changes: 47 additions & 0 deletions cmuxTests/DefaultBrowserAuthSessionFactoryTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import CmuxAuthRuntime
import Foundation
import Testing

#if canImport(cmux_DEV)
@testable import cmux_DEV
#elseif canImport(cmux)
@testable import cmux
#endif

@MainActor
@Suite struct DefaultBrowserAuthSessionFactoryTests {
@Test func startOpensSignInURLAndWaitsForExternalCallback() {
let signInURL = URL(string: "https://cmux.test/handler/native-sign-in")!
var openedURLs: [URL] = []
var completions = 0
let factory = DefaultBrowserAuthSessionFactory { url in
openedURLs.append(url)
return true
}

let session = factory.makeSession(
signInURL: signInURL,
callbackScheme: "cmux"
) { _ in
completions += 1
}

#expect(session.start())
#expect(openedURLs == [signInURL])
#expect(completions == 0)

session.cancel()
#expect(completions == 0)
}

@Test func startReportsFailureWhenDefaultBrowserOpenFails() {
let factory = DefaultBrowserAuthSessionFactory { _ in false }
let session = factory.makeSession(
signInURL: URL(string: "https://cmux.test/handler/native-sign-in")!,
callbackScheme: "cmux",
completion: { _ in }
)

#expect(session.start() == false)
}
}
Loading