Repository navigation
Vendor CEFWebView Swift package (Phase 1: chromium browser engine) #2945
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |
|
|
||
| /* Begin PBXBuildFile section */ | ||
| FE001101 /* FileExplorerStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE001001 /* FileExplorerStore.swift */; }; | ||
| CEF00200 /* CefDebugWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEF00201 /* CefDebugWindow.swift */; }; | ||
| FE001102 /* FileExplorerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE001002 /* FileExplorerView.swift */; }; | ||
| FE002101 /* FileExplorerRootResolverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE002001 /* FileExplorerRootResolverTests.swift */; }; | ||
| FE002102 /* FileExplorerStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = FE002002 /* FileExplorerStoreTests.swift */; }; | ||
|
|
@@ -212,6 +213,7 @@ | |
|
|
||
| /* Begin PBXFileReference section */ | ||
| FE001001 /* FileExplorerStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileExplorerStore.swift; sourceTree = "<group>"; }; | ||
| CEF00201 /* CefDebugWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CefDebugWindow.swift; sourceTree = "<group>"; }; | ||
| FE001002 /* FileExplorerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileExplorerView.swift; sourceTree = "<group>"; }; | ||
| FE002001 /* FileExplorerRootResolverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileExplorerRootResolverTests.swift; sourceTree = "<group>"; }; | ||
| FE002002 /* FileExplorerStoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileExplorerStoreTests.swift; sourceTree = "<group>"; }; | ||
|
|
@@ -533,6 +535,7 @@ | |
| A5001655 /* CmuxDirectoryTrust.swift */, | ||
| FE001001 /* FileExplorerStore.swift */, | ||
| FE001002 /* FileExplorerView.swift */, | ||
| CEF00201 /* CefDebugWindow.swift */, | ||
| ); | ||
| path = Sources; | ||
| sourceTree = "<group>"; | ||
|
|
@@ -661,6 +664,7 @@ | |
| A5001271 /* PostHog */, | ||
| A5001261 /* Bonsplit */, | ||
| A5001291 /* MarkdownUI */, | ||
| CEF00101 /* CEFWebView */, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Adding Useful? React with 👍 / 👎. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: CEFWebView is added as a package dependency but not linked in the target’s Frameworks build phase. Prompt for AI agents |
||
| ); | ||
| name = GhosttyTabs; | ||
| productName = GhosttyTabs; | ||
|
|
@@ -781,6 +785,7 @@ | |
| A5001272 /* XCRemoteSwiftPackageReference "posthog-ios" */, | ||
| A5001292 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */, | ||
| A5001260 /* XCLocalSwiftPackageReference "bonsplit" */, | ||
| CEF00100 /* XCLocalSwiftPackageReference "CEFWebView" */, | ||
| ); | ||
| productRefGroup = A5001042 /* Products */; | ||
| projectDirPath = ""; | ||
|
|
@@ -864,6 +869,7 @@ | |
| A5001654 /* CmuxDirectoryTrust.swift in Sources */, | ||
| FE001101 /* FileExplorerStore.swift in Sources */, | ||
| FE001102 /* FileExplorerView.swift in Sources */, | ||
| CEF00200 /* CefDebugWindow.swift in Sources */, | ||
| ); | ||
| runOnlyForDeploymentPostprocessing = 0; | ||
| }; | ||
|
|
@@ -1047,11 +1053,19 @@ | |
| DEVELOPMENT_TEAM = ""; | ||
| ENABLE_HARDENED_RUNTIME = NO; | ||
| GENERATE_INFOPLIST_FILE = NO; | ||
| FRAMEWORK_SEARCH_PATHS = ( | ||
| "$(inherited)", | ||
| "$(SRCROOT)/vendor/CEFWebView/Frameworks", | ||
| ); | ||
| INFOPLIST_FILE = Resources/Info.plist; | ||
| LD_RUNPATH_SEARCH_PATHS = ( | ||
| "$(inherited)", | ||
| "@executable_path/../Frameworks", | ||
| ); | ||
| LIBRARY_SEARCH_PATHS = ( | ||
| "$(inherited)", | ||
| "$(SRCROOT)/vendor/CEFWebView/Frameworks", | ||
| ); | ||
|
Comment on lines
+1056
to
+1068
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CEFWebView is wired into Release builds but no Embed Frameworks step exists for The Release config ( Per the PR description this is a Phase-2 spike not intended for dogfooding, but it's worth either (a) gating the package product dependency / search paths behind a Debug-only xcconfig, or (b) adding a 🤖 Prompt for AI Agents |
||
| MARKETING_VERSION = 0.63.2; | ||
| OTHER_LDFLAGS = ( | ||
| "-lc++", | ||
|
|
@@ -1086,11 +1100,19 @@ | |
| DEVELOPMENT_TEAM = ""; | ||
| ENABLE_HARDENED_RUNTIME = NO; | ||
| GENERATE_INFOPLIST_FILE = NO; | ||
| FRAMEWORK_SEARCH_PATHS = ( | ||
| "$(inherited)", | ||
| "$(SRCROOT)/vendor/CEFWebView/Frameworks", | ||
| ); | ||
| INFOPLIST_FILE = Resources/Info.plist; | ||
| LD_RUNPATH_SEARCH_PATHS = ( | ||
| "$(inherited)", | ||
| "@executable_path/../Frameworks", | ||
| ); | ||
| LIBRARY_SEARCH_PATHS = ( | ||
| "$(inherited)", | ||
| "$(SRCROOT)/vendor/CEFWebView/Frameworks", | ||
| ); | ||
| MARKETING_VERSION = 0.63.2; | ||
| OTHER_LDFLAGS = ( | ||
| "-lc++", | ||
|
|
@@ -1312,6 +1334,10 @@ | |
| isa = XCLocalSwiftPackageReference; | ||
| relativePath = vendor/bonsplit; | ||
| }; | ||
| CEF00100 /* XCLocalSwiftPackageReference "CEFWebView" */ = { | ||
| isa = XCLocalSwiftPackageReference; | ||
| relativePath = vendor/CEFWebView; | ||
| }; | ||
| /* End XCRemoteSwiftPackageReference section */ | ||
|
|
||
| /* Begin XCSwiftPackageProductDependency section */ | ||
|
|
@@ -1340,6 +1366,11 @@ | |
| package = A5001292 /* XCRemoteSwiftPackageReference "swift-markdown-ui" */; | ||
| productName = MarkdownUI; | ||
| }; | ||
| CEF00101 /* CEFWebView */ = { | ||
| isa = XCSwiftPackageProductDependency; | ||
| package = CEF00100 /* XCLocalSwiftPackageReference "CEFWebView" */; | ||
| productName = CEFWebView; | ||
| }; | ||
| /* End XCSwiftPackageProductDependency section */ | ||
|
|
||
| /* Begin XCConfigurationList section */ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| import AppKit | ||
| import CEFWebView | ||
| import SwiftUI | ||
|
|
||
| /// Debug-only window hosting a CEFWebView (Chromium) so we can dogfood the | ||
| /// engine before plumbing it into BrowserPanel. Open via Debug > Debug Windows > | ||
| /// Chromium (CEF)… | ||
| @MainActor | ||
| final class CefDebugWindowController: NSWindowController, NSWindowDelegate { | ||
| static let shared = CefDebugWindowController() | ||
|
|
||
| private init() { | ||
| let window = NSWindow( | ||
| contentRect: NSRect(x: 0, y: 0, width: 1024, height: 720), | ||
| styleMask: [.titled, .closable, .miniaturizable, .resizable], | ||
| backing: .buffered, | ||
| defer: false | ||
| ) | ||
| window.title = "Chromium (CEF)" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. User-facing strings are not localized.
As per coding guidelines: "All user-facing strings must be localized. Use Also applies to: 66-66, 86-86 🤖 Prompt for AI Agents |
||
| window.identifier = NSUserInterfaceItemIdentifier("cmux.cefDebug") | ||
| window.isReleasedWhenClosed = false | ||
| window.center() | ||
| window.contentView = NSHostingView(rootView: CefDebugView()) | ||
| super.init(window: window) | ||
| window.delegate = self | ||
| } | ||
|
|
||
| @available(*, unavailable) | ||
| required init?(coder: NSCoder) { | ||
| fatalError("init(coder:) has not been implemented") | ||
| } | ||
|
|
||
| func show() { | ||
| window?.makeKeyAndOrderFront(nil) | ||
| } | ||
| } | ||
|
|
||
| private struct CefDebugView: View { | ||
| @State private var url: URL? = URL(string: "https://www.google.com") | ||
| @State private var urlText: String = "https://www.google.com" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Prompt for AI agents |
||
| @State private var state = CEFWebViewState() | ||
|
|
||
| var body: some View { | ||
| VStack(spacing: 0) { | ||
| HStack(spacing: 6) { | ||
| Button { | ||
| state.goBack() | ||
| } label: { | ||
| Image(systemName: "chevron.left") | ||
| } | ||
| .disabled(!state.canGoBack) | ||
|
|
||
| Button { | ||
| state.goForward() | ||
| } label: { | ||
| Image(systemName: "chevron.right") | ||
| } | ||
| .disabled(!state.canGoForward) | ||
|
|
||
| Button { | ||
| state.reload() | ||
| } label: { | ||
| Image(systemName: "arrow.clockwise") | ||
| } | ||
|
|
||
| TextField("URL", text: $urlText) | ||
| .textFieldStyle(.roundedBorder) | ||
| .onSubmit { | ||
| if let parsed = parseURL(urlText) { | ||
| url = parsed | ||
| } | ||
| } | ||
|
Comment on lines
+66
to
+72
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🤖 Prompt for AI Agents |
||
| } | ||
| .padding(8) | ||
|
|
||
| Divider() | ||
|
|
||
| ZStack { | ||
| CEFWebView(url: $url, state: $state) | ||
|
|
||
| if let err = state.initializationError { | ||
| VStack(spacing: 12) { | ||
| Image(systemName: "exclamationmark.triangle.fill") | ||
| .font(.largeTitle) | ||
| .foregroundStyle(.yellow) | ||
| Text("CEF initialization failed") | ||
| .font(.headline) | ||
| ScrollView { | ||
| Text(err) | ||
| .font(.system(.caption, design: .monospaced)) | ||
| .textSelection(.enabled) | ||
| .padding() | ||
| } | ||
| } | ||
| .padding() | ||
| .background(.regularMaterial) | ||
| } | ||
| } | ||
|
|
||
| HStack { | ||
| if state.isLoading { | ||
| ProgressView().controlSize(.small) | ||
| } | ||
| Text(state.title ?? state.currentURL?.absoluteString ?? "") | ||
| .font(.caption) | ||
| .lineLimit(1) | ||
| .truncationMode(.middle) | ||
| Spacer() | ||
| if state.rendererHelperFailed { | ||
| Text(state.rendererFailureStatusLine) | ||
| .font(.caption) | ||
| .foregroundStyle(.red) | ||
| } | ||
| } | ||
| .padding(.horizontal, 8) | ||
| .padding(.vertical, 4) | ||
| } | ||
| } | ||
|
|
||
| private func parseURL(_ text: String) -> URL? { | ||
| let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines) | ||
| guard !trimmed.isEmpty else { return nil } | ||
| if trimmed.contains("://") { | ||
| return URL(string: trimmed) | ||
| } | ||
| return URL(string: "https://\(trimmed)") | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -488,6 +488,9 @@ struct cmuxApp: App { | |||||||||||||||||||
| Button("Background Debug…") { | ||||||||||||||||||||
| BackgroundDebugWindowController.shared.show() | ||||||||||||||||||||
| } | ||||||||||||||||||||
| Button("Chromium (CEF)…") { | ||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Localize the new Debug menu label. Line 491 adds a user-facing bare string literal ( Suggested patch- Button("Chromium (CEF)…") {
+ Button(
+ String(
+ localized: "debug.menu.chromiumCef",
+ defaultValue: "Chromium (CEF)…"
+ )
+ ) {
CefDebugWindowController.shared.show()
}As per coding guidelines, “All user-facing strings must be localized. Use 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||
| CefDebugWindowController.shared.show() | ||||||||||||||||||||
| } | ||||||||||||||||||||
| Button("Browser Import Hint Debug…") { | ||||||||||||||||||||
| BrowserImportHintDebugWindowController.shared.show() | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: manaflow-ai/cmux
Length of output: 1417
🏁 Script executed:
fd -i 'cefdebugwindow.swift' -x cat -n {}Repository: manaflow-ai/cmux
Length of output: 5200
🏁 Script executed:
Repository: manaflow-ai/cmux
Length of output: 42
🏁 Script executed:
Repository: manaflow-ai/cmux
Length of output: 1025
Wrap
CefDebugWindow.swiftentirely in#if DEBUG/#endif.The file imports
CEFWebViewand is added unconditionally to the build sources (line 872). Since CEFWebView is not embedded in Release builds, the file must be guarded with#if DEBUGat the top and#endifat the end to prevent link failures.Also applies to: 872-872
🤖 Prompt for AI Agents