Skip to content

Commit

Permalink
Bugfix FXIOS-9483 Bugzilla 1905749 (#22519)
Browse files Browse the repository at this point in the history
* Bugfix FXIOS-9483 Bugzilla 1905749

* Cleanup
  • Loading branch information
nbhasin2 authored Oct 24, 2024
1 parent 1193861 commit c529d9f
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,18 @@ extension BrowserViewController: WKUIDelegate {
return nil
}

let navigationUrl = navigationAction.request.url
let navigationUrlString = navigationUrl?.absoluteString ?? ""

// Check for "data" scheme using WebViewNavigationHandlerImplementation
let navigationHandler = WebViewNavigationHandlerImplementation { _ in }
var shouldAllowDataScheme = true
if navigationHandler.shouldFilterDataScheme(url: navigationUrl) {
shouldAllowDataScheme = navigationHandler.shouldAllowDataScheme(for: navigationUrl)
}

guard shouldAllowDataScheme else { return nil }

// If the page uses `window.open()` or `[target="_blank"]`, open the page in a new tab.
// IMPORTANT!!: WebKit will perform the `URLRequest` automatically!! Attempting to do
// the request here manually leads to incorrect results!!
Expand All @@ -44,7 +56,7 @@ extension BrowserViewController: WKUIDelegate {
configuration: configuration
)

if navigationAction.request.url == nil {
if navigationUrl == nil || navigationUrlString.isEmpty {
newTab.url = URL(string: "about:blank")
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ protocol WebViewNavigationHandler {

/// Whether we should filter that URL for data scheme or not
/// - Returns: True when the URL needs to be filtered for the data scheme
func shouldFilterDataScheme(url: URL) -> Bool
func shouldFilterDataScheme(url: URL?) -> Bool

/// Filter top-level data scheme has defined in:
/// https://blog.mozilla.org/security/2017/11/27/blocking-top-level-navigations-data-urls-firefox-59/
Expand All @@ -38,7 +38,8 @@ struct WebViewNavigationHandlerImplementation: WebViewNavigationHandler {
self.decisionHandler = decisionHandler
}

func shouldFilterDataScheme(url: URL) -> Bool {
func shouldFilterDataScheme(url: URL?) -> Bool {
guard let url else { return false }
return url.scheme == WebViewNavigationHandlerImplementation.Scheme.data.rawValue
}

Expand All @@ -51,32 +52,39 @@ struct WebViewNavigationHandlerImplementation: WebViewNavigationHandler {
return
}

let url = url.absoluteString.lowercased()
// Allow certain image types
if url.hasPrefix("data:image/") && !url.hasPrefix("data:image/svg+xml") {
if shouldAllowDataScheme(for: url) {
decisionHandler(.allow)
return
} else {
decisionHandler(.cancel)
}
}

func shouldAllowDataScheme(for url: URL?) -> Bool {
guard let url else { return false }
let urlString = url.absoluteString.lowercased()

// Allow certain image types
if urlString.hasPrefix("data:image/") && !urlString.hasPrefix("data:image/svg+xml") {
return true
}

// Allow video, and certain application types
if url.hasPrefix("data:video/")
|| url.hasPrefix("data:application/pdf")
|| url.hasPrefix("data:application/json") {
decisionHandler(.allow)
return
if urlString.hasPrefix("data:video/")
|| urlString.hasPrefix("data:application/pdf")
|| urlString.hasPrefix("data:application/json") {
return true
}

// Allow plain text types.
// Note the format of data URLs is `data:[<media type>][;base64],<data>`
// Note the format of data URLs is `data:[<media type>][;base64],<data>`
// with empty <media type> indicating plain text.
if url.hasPrefix("data:;base64,")
|| url.hasPrefix("data:,")
|| url.hasPrefix("data:text/plain,")
|| url.hasPrefix("data:text/plain;") {
decisionHandler(.allow)
return
if urlString.hasPrefix("data:;base64,")
|| urlString.hasPrefix("data:,")
|| urlString.hasPrefix("data:text/plain,")
|| urlString.hasPrefix("data:text/plain;") {
return true
}

decisionHandler(.cancel)
return false
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,6 @@ class LegacyTabManager: NSObject, FeatureFlaggable, TabManager, TabEventHandler
let popup = Tab(profile: profile,
isPrivate: parentTab.isPrivate,
windowUUID: windowUUID)

// Configure the tab for the child popup webview. In this scenario we need to be sure to pass along
// the specific `configuration` that we are given by the WKUIDelegate callback, since if we do not
// use this configuration WebKit will throw an exception.
Expand Down

0 comments on commit c529d9f

Please sign in to comment.