Skip to content
Merged
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
43 changes: 41 additions & 2 deletions Sources/Panels/BrowserPanel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2987,16 +2987,41 @@ final class BrowserPanel: Panel, ObservableObject {
) {
let restoredBack = Self.sanitizedSessionHistoryURLs(backHistoryURLStrings)
let restoredForward = Self.sanitizedSessionHistoryURLs(forwardHistoryURLStrings)
guard !restoredBack.isEmpty || !restoredForward.isEmpty else { return }
let restoredCurrent = Self.sanitizedSessionHistoryURL(currentURLString)
guard !restoredBack.isEmpty || !restoredForward.isEmpty || restoredCurrent != nil else { return }

usesRestoredSessionHistory = true
restoredBackHistoryStack = restoredBack
// Store nearest-forward entries at the end to make stack pop operations trivial.
restoredForwardHistoryStack = Array(restoredForward.reversed())
restoredHistoryCurrentURL = Self.sanitizedSessionHistoryURL(currentURLString)
restoredHistoryCurrentURL = restoredCurrent
refreshNavigationAvailability()
}

func restoreSessionSnapshot(_ snapshot: SessionBrowserPanelSnapshot) {
let restoredURL = Self.sanitizedSessionHistoryURL(snapshot.urlString)

restoreSessionNavigationHistory(
backHistoryURLStrings: snapshot.backHistoryURLStrings ?? [],
forwardHistoryURLStrings: snapshot.forwardHistoryURLStrings ?? [],
currentURLString: snapshot.urlString
)

currentURL = snapshot.shouldRenderWebView ? restoredURL : nil
shouldRenderWebView = snapshot.shouldRenderWebView

guard snapshot.shouldRenderWebView, let restoredURL else {
refreshNavigationAvailability()
return
}
Comment on lines +3010 to +3016

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Blank WebView when shouldRenderWebView is true but URL is unsanitizable

If snapshot.shouldRenderWebView is true but Self.sanitizedSessionHistoryURL(snapshot.urlString) returns nil (e.g. corrupt/missing URL in persisted data), the code sets shouldRenderWebView = true and currentURL = nil, then takes the early-return branch. The WebView will be rendered but completely blank rather than falling back to the new-tab/empty state.

The old code would have called newBrowserSurface(url: nil), leaving shouldRenderWebView = false (no navigation triggered), so the user would have seen a clean new-tab page instead.

In practice this can't happen with a valid session file because shouldRenderWebView is serialised from browserPanel.shouldRenderWebView, which is only set to true alongside a real navigation. But it's worth guarding explicitly so corrupt sessions degrade gracefully:

currentURL = (snapshot.shouldRenderWebView && restoredURL != nil) ? restoredURL : nil
shouldRenderWebView = snapshot.shouldRenderWebView && restoredURL != nil


navigateWithoutInsecureHTTPPrompt(
to: restoredURL,
recordTypedNavigation: false,
preserveRestoredSessionHistory: true
)
}

private func setupObservers(for webView: WKWebView) {
let observedWebViewInstanceID = webViewInstanceID

Expand Down Expand Up @@ -4132,6 +4157,20 @@ extension BrowserPanel {
/// Reload the current page
func reload() {
webView.customUserAgent = BrowserUserAgentSettings.safariUserAgent
if Self.serializableSessionHistoryURLString(Self.remoteProxyDisplayURL(for: webView.url)) == nil {
let fallbackURL = resolvedCurrentSessionHistoryURL()
?? Self.remoteProxyDisplayURL(for: navigationDelegate?.lastAttemptedURL)

if let fallbackURL,
Self.serializableSessionHistoryURLString(fallbackURL) != nil {
navigateWithoutInsecureHTTPPrompt(
to: fallbackURL,
recordTypedNavigation: false,
preserveRestoredSessionHistory: usesRestoredSessionHistory
)
return
}
}
webView.reload()
}

Expand Down
11 changes: 3 additions & 8 deletions Sources/Workspace.swift
Original file line number Diff line number Diff line change
Expand Up @@ -596,10 +596,9 @@ extension Workspace {
applySessionPanelMetadata(snapshot, toPanelId: terminalPanel.id)
return terminalPanel.id
case .browser:
let initialURL = snapshot.browser?.urlString.flatMap { URL(string: $0) }
guard let browserPanel = newBrowserSurface(
inPane: paneId,
url: initialURL,
url: nil,
focus: false,
preferredProfileID: snapshot.browser?.profileID
) else {
Expand Down Expand Up @@ -655,17 +654,13 @@ extension Workspace {

if let browserSnapshot = snapshot.browser,
let browserPanel = browserPanel(for: panelId) {
browserPanel.restoreSessionNavigationHistory(
backHistoryURLStrings: browserSnapshot.backHistoryURLStrings ?? [],
forwardHistoryURLStrings: browserSnapshot.forwardHistoryURLStrings ?? [],
currentURLString: browserSnapshot.urlString
)

let pageZoom = CGFloat(max(0.25, min(5.0, browserSnapshot.pageZoom)))
if pageZoom.isFinite {
_ = browserPanel.setPageZoomFactor(pageZoom)
}

browserPanel.restoreSessionSnapshot(browserSnapshot)

if browserSnapshot.developerToolsVisible {
_ = browserPanel.showDeveloperTools()
browserPanel.requestDeveloperToolsRefreshAfterNextAttach(reason: "session_restore")
Expand Down
Loading