Share browser context with OAuth popups (#1600)
* Add popup browser context regression tests * Share browser context with OAuth popups --------- Co-authored-by: Lawrence Chen <lawrencecchen@users.noreply.github.com>
This commit is contained in:
parent
886de2a7c9
commit
cc0fc557cf
3 changed files with 93 additions and 29 deletions
|
|
@ -2447,33 +2447,9 @@ final class BrowserPanel: Panel, ObservableObject {
|
|||
websiteDataStore: WKWebsiteDataStore? = nil
|
||||
) -> CmuxWebView {
|
||||
let config = WKWebViewConfiguration()
|
||||
config.processPool = BrowserPanel.sharedProcessPool
|
||||
config.mediaTypesRequiringUserActionForPlayback = []
|
||||
// Ensure browser cookies/storage persist across navigations and launches.
|
||||
// This reduces repeated consent/bot-challenge flows on sites like Google.
|
||||
config.websiteDataStore = websiteDataStore ?? BrowserProfileStore.shared.websiteDataStore(for: profileID)
|
||||
|
||||
// Enable developer extras (DevTools)
|
||||
config.preferences.setValue(true, forKey: "developerExtrasEnabled")
|
||||
|
||||
// Enable JavaScript
|
||||
config.defaultWebpagePreferences.allowsContentJavaScript = true
|
||||
// Keep browser console/error/dialog telemetry active from document start on every navigation.
|
||||
config.userContentController.addUserScript(
|
||||
WKUserScript(
|
||||
source: Self.telemetryHookBootstrapScriptSource,
|
||||
injectionTime: .atDocumentStart,
|
||||
forMainFrameOnly: false
|
||||
)
|
||||
)
|
||||
// Track the last editable focused element continuously so omnibar exit can
|
||||
// restore page input focus even if capture runs after first-responder handoff.
|
||||
config.userContentController.addUserScript(
|
||||
WKUserScript(
|
||||
source: Self.addressBarFocusTrackingBootstrapScript,
|
||||
injectionTime: .atDocumentStart,
|
||||
forMainFrameOnly: false
|
||||
)
|
||||
configureWebViewConfiguration(
|
||||
config,
|
||||
websiteDataStore: websiteDataStore ?? BrowserProfileStore.shared.websiteDataStore(for: profileID)
|
||||
)
|
||||
|
||||
let webView = CmuxWebView(frame: .zero, configuration: config)
|
||||
|
|
@ -2489,6 +2465,41 @@ final class BrowserPanel: Panel, ObservableObject {
|
|||
return webView
|
||||
}
|
||||
|
||||
static func configureWebViewConfiguration(
|
||||
_ configuration: WKWebViewConfiguration,
|
||||
websiteDataStore: WKWebsiteDataStore,
|
||||
processPool: WKProcessPool = BrowserPanel.sharedProcessPool
|
||||
) {
|
||||
configuration.processPool = processPool
|
||||
configuration.mediaTypesRequiringUserActionForPlayback = []
|
||||
// Ensure browser cookies/storage persist across navigations and launches.
|
||||
// This reduces repeated consent/bot-challenge flows on sites like Google.
|
||||
configuration.websiteDataStore = websiteDataStore
|
||||
|
||||
// Enable developer extras (DevTools)
|
||||
configuration.preferences.setValue(true, forKey: "developerExtrasEnabled")
|
||||
|
||||
// Enable JavaScript
|
||||
configuration.defaultWebpagePreferences.allowsContentJavaScript = true
|
||||
// Keep browser console/error/dialog telemetry active from document start on every navigation.
|
||||
configuration.userContentController.addUserScript(
|
||||
WKUserScript(
|
||||
source: Self.telemetryHookBootstrapScriptSource,
|
||||
injectionTime: .atDocumentStart,
|
||||
forMainFrameOnly: false
|
||||
)
|
||||
)
|
||||
// Track the last editable focused element continuously so omnibar exit can
|
||||
// restore page input focus even if capture runs after first-responder handoff.
|
||||
configuration.userContentController.addUserScript(
|
||||
WKUserScript(
|
||||
source: Self.addressBarFocusTrackingBootstrapScript,
|
||||
injectionTime: .atDocumentStart,
|
||||
forMainFrameOnly: false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private func bindWebView(_ webView: CmuxWebView) {
|
||||
webView.onContextMenuDownloadStateChanged = { [weak self] downloading in
|
||||
if downloading {
|
||||
|
|
|
|||
|
|
@ -92,13 +92,24 @@ final class BrowserPopupWindowController: NSObject, NSWindowDelegate {
|
|||
self.parentPopupController = parentPopupController
|
||||
self.nestingDepth = nestingDepth
|
||||
|
||||
// Create popup web view with WebKit's supplied configuration (preserves
|
||||
// internal browsing-context state for opener linkage / postMessage).
|
||||
let browserContextSource = parentPopupController?.webView.configuration ?? openerPanel?.webView.configuration
|
||||
if let browserContextSource {
|
||||
BrowserPanel.configureWebViewConfiguration(
|
||||
configuration,
|
||||
websiteDataStore: browserContextSource.websiteDataStore,
|
||||
processPool: browserContextSource.processPool
|
||||
)
|
||||
}
|
||||
|
||||
// Create popup web view with WebKit's supplied configuration after
|
||||
// overlaying the opener's browser context so OAuth popups keep cmux's
|
||||
// shared cookie/storage scope and opener linkage.
|
||||
let webView = CmuxWebView(frame: .zero, configuration: configuration)
|
||||
webView.allowsBackForwardNavigationGestures = true
|
||||
if #available(macOS 13.3, *) {
|
||||
webView.isInspectable = true
|
||||
}
|
||||
webView.underPageBackgroundColor = GhosttyBackgroundTheme.currentColor()
|
||||
webView.customUserAgent = BrowserUserAgentSettings.safariUserAgent
|
||||
self.webView = webView
|
||||
|
||||
|
|
|
|||
|
|
@ -1003,6 +1003,48 @@ final class GhosttyTerminalStartupEnvironmentTests: XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
final class BrowserPanelPopupContextTests: XCTestCase {
|
||||
func testFloatingPopupInheritsOpenerBrowserContext() throws {
|
||||
let panel = BrowserPanel(workspaceId: UUID(), isRemoteWorkspace: false)
|
||||
let popupWebView = try XCTUnwrap(
|
||||
panel.createFloatingPopup(
|
||||
configuration: WKWebViewConfiguration(),
|
||||
windowFeatures: WKWindowFeatures()
|
||||
)
|
||||
)
|
||||
defer { popupWebView.window?.close() }
|
||||
|
||||
XCTAssertTrue(
|
||||
popupWebView.configuration.processPool === panel.webView.configuration.processPool
|
||||
)
|
||||
XCTAssertTrue(
|
||||
popupWebView.configuration.websiteDataStore === panel.webView.configuration.websiteDataStore
|
||||
)
|
||||
}
|
||||
|
||||
func testFloatingPopupInheritsRemoteWorkspaceWebsiteDataStore() throws {
|
||||
let remoteWorkspaceId = UUID()
|
||||
let panel = BrowserPanel(
|
||||
workspaceId: remoteWorkspaceId,
|
||||
isRemoteWorkspace: true,
|
||||
remoteWebsiteDataStoreIdentifier: remoteWorkspaceId
|
||||
)
|
||||
let popupWebView = try XCTUnwrap(
|
||||
panel.createFloatingPopup(
|
||||
configuration: WKWebViewConfiguration(),
|
||||
windowFeatures: WKWindowFeatures()
|
||||
)
|
||||
)
|
||||
defer { popupWebView.window?.close() }
|
||||
|
||||
XCTAssertTrue(
|
||||
popupWebView.configuration.websiteDataStore === panel.webView.configuration.websiteDataStore
|
||||
)
|
||||
XCTAssertFalse(popupWebView.configuration.websiteDataStore === WKWebsiteDataStore.default())
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
final class BrowserPanelRemoteStoreTests: XCTestCase {
|
||||
func testRemoteWorkspacePanelsShareWorkspaceScopedWebsiteDataStore() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue