Skip to content

Commit

Permalink
[iOS] Remove tab storage on all tab content scripts
Browse files Browse the repository at this point in the history
This change prepares for using the Chromium web embedder by removing weak storage of `Tab` objects passed in when creating classes confomring to `TabContentScript` which better matches `JavaScriptFeature` and its requirements
  • Loading branch information
kylehickinson committed Jan 8, 2025
1 parent d865125 commit a6857a4
Show file tree
Hide file tree
Showing 44 changed files with 379 additions and 584 deletions.
12 changes: 3 additions & 9 deletions ios/brave-ios/Sources/Brave/Frontend/Browser/BraveGetUA.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ import Shared
import WebKit

class BraveGetUA: TabContentScript {
fileprivate weak var tab: Tab?

required init(tab: Tab) {
self.tab = tab
}

static let scriptName = "BraveGetUA"
static let scriptId = UUID().uuidString
static let messageHandlerName = "\(scriptName)_\(messageUUID)"
Expand All @@ -34,9 +28,9 @@ class BraveGetUA: TabContentScript {
)
}()

func userContentController(
_ userContentController: WKUserContentController,
didReceiveScriptMessage message: WKScriptMessage,
func tab(
_ tab: Tab,
receivedScriptMessage message: WKScriptMessage,
replyHandler: (Any?, String?) -> Void
) {
// 🙀 😭 🏃‍♀️💨
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ extension BrowserViewController: ReaderModeStyleViewControllerDelegate {
as? ReaderModeScriptHandler
{
if readerMode.state == ReaderModeState.active {
readerMode.style = style
readerMode.setStyle(style, in: tab)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -729,8 +729,7 @@ extension BrowserViewController: WKNavigationDelegate {

// We can only show this content in the web view if this web view is not pending
// download via the context menu.
let canShowInWebView = navigationResponse.canShowMIMEType && (webView != pendingDownloadWebView)
let forceDownload = webView == pendingDownloadWebView
let canShowInWebView = navigationResponse.canShowMIMEType

let mimeTypesThatRequireSFSafariViewControllerHandling: [UTType] = [
.textCalendar,
Expand Down Expand Up @@ -823,13 +822,8 @@ extension BrowserViewController: WKNavigationDelegate {
request: request,
response: response,
cookieStore: cookieStore,
canShowInWebView: canShowInWebView,
forceDownload: forceDownload
canShowInWebView: canShowInWebView
) {
// Clear the pending download web view so that subsequent navigations from the same
// web view don't invoke another download.
pendingDownloadWebView = nil

let downloadAlertAction: (HTTPDownload) -> Void = { [weak self] download in
self?.downloadQueue.enqueue(download)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,6 @@ public class BrowserViewController: UIViewController {
// allow us to re-trigger the `URLRequest` if the user requests a file to be downloaded.
var pendingRequests = [String: URLRequest]()

// This is set when the user taps "Download Link" from the context menu. We then force a
// download of the next request through the `WKNavigationDelegate` that matches this web view.
weak var pendingDownloadWebView: WKWebView?

let downloadQueue = DownloadQueue()

private var cancellables: Set<AnyCancellable> = []
Expand Down Expand Up @@ -2615,32 +2611,33 @@ extension BrowserViewController: TabDelegate {
webView.uiDelegate = self

var injectedScripts: [TabContentScript] = [
ReaderModeScriptHandler(tab: tab),
ReaderModeScriptHandler(),
ErrorPageHelper(certStore: profile.certStore),
SessionRestoreScriptHandler(tab: tab),
BlockedDomainScriptHandler(tab: tab),
HTTPBlockedScriptHandler(tab: tab, tabManager: tabManager),
PrintScriptHandler(browserController: self, tab: tab),
CustomSearchScriptHandler(tab: tab),
DarkReaderScriptHandler(tab: tab),
FocusScriptHandler(tab: tab),
BraveGetUA(tab: tab),
BraveSearchScriptHandler(tab: tab, profile: profile, rewards: rewards),
ResourceDownloadScriptHandler(tab: tab),
DownloadContentScriptHandler(browserController: self, tab: tab),
SessionRestoreScriptHandler(),
BlockedDomainScriptHandler(),
HTTPBlockedScriptHandler(tabManager: tabManager),
PrintScriptHandler(browserController: self),
CustomSearchScriptHandler(),
DarkReaderScriptHandler(),
FocusScriptHandler(),
BraveGetUA(),
BraveSearchScriptHandler(profile: profile, rewards: rewards),
ResourceDownloadScriptHandler(),
DownloadContentScriptHandler(browserController: self),
PlaylistScriptHandler(tab: tab),
PlaylistFolderSharingScriptHandler(tab: tab),
RewardsReportingScriptHandler(rewards: rewards, tab: tab),
AdsMediaReportingScriptHandler(rewards: rewards, tab: tab),
ReadyStateScriptHandler(tab: tab),
DeAmpScriptHandler(tab: tab),
SiteStateListenerScriptHandler(tab: tab),
CosmeticFiltersScriptHandler(tab: tab),
URLPartinessScriptHandler(tab: tab),
FaviconScriptHandler(tab: tab),
Web3NameServiceScriptHandler(tab: tab),
PlaylistFolderSharingScriptHandler(),
RewardsReportingScriptHandler(rewards: rewards),
AdsMediaReportingScriptHandler(rewards: rewards),
ReadyStateScriptHandler(),
DeAmpScriptHandler(),
SiteStateListenerScriptHandler(),
CosmeticFiltersScriptHandler(),
URLPartinessScriptHandler(),
FaviconScriptHandler(),
Web3NameServiceScriptHandler(),
YoutubeQualityScriptHandler(tab: tab),
BraveLeoScriptHandler(tab: tab),
BraveLeoScriptHandler(),
BraveSkusScriptHandler(),

tab.contentBlocker,
tab.requestBlockingContentHelper,
Expand All @@ -2649,7 +2646,6 @@ extension BrowserViewController: TabDelegate {
#if canImport(BraveTalk)
injectedScripts.append(
BraveTalkScriptHandler(
tab: tab,
rewards: rewards,
launchNativeBraveTalk: { [weak self] tab, room, token in
self?.launchNativeBraveTalk(tab: tab, room: room, token: token)
Expand All @@ -2658,17 +2654,13 @@ extension BrowserViewController: TabDelegate {
)
#endif

if let braveSkusHandler = BraveSkusScriptHandler(tab: tab) {
injectedScripts.append(braveSkusHandler)
}

// Only add the logins handler and wallet provider if the tab is NOT a private browsing tab
if !tab.isPrivate {
injectedScripts += [
LoginsScriptHandler(tab: tab, profile: profile, passwordAPI: braveCore.passwordAPI),
EthereumProviderScriptHandler(tab: tab),
SolanaProviderScriptHandler(tab: tab),
BraveSearchResultAdScriptHandler(tab: tab),
LoginsScriptHandler(profile: profile, passwordAPI: braveCore.passwordAPI),
EthereumProviderScriptHandler(),
SolanaProviderScriptHandler(),
BraveSearchResultAdScriptHandler(),
]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ import Foundation
import WebKit

class FingerprintingProtection: TabContentScript {
fileprivate weak var tab: Tab?

init(tab: Tab) {
self.tab = tab
}

static let scriptName = "FingerprintingProtection"
static let scriptId = UUID().uuidString
static let messageHandlerName = "\(scriptName)_\(messageUUID)"
Expand All @@ -34,15 +28,14 @@ class FingerprintingProtection: TabContentScript {
)
}()

func userContentController(
_ userContentController: WKUserContentController,
didReceiveScriptMessage message: WKScriptMessage,
func tab(
_ tab: Tab,
receivedScriptMessage message: WKScriptMessage,
replyHandler: (Any?, String?) -> Void
) {
defer { replyHandler(nil, nil) }
if let stats = self.tab?.contentBlocker.stats {
self.tab?.contentBlocker.stats = stats.adding(fingerprintingCount: 1)
BraveGlobalShieldStats.shared.fpProtection += 1
}
let stats = tab.contentBlocker.stats
tab.contentBlocker.stats = stats.adding(fingerprintingCount: 1)
BraveGlobalShieldStats.shared.fpProtection += 1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,7 @@ class DownloadHelper: NSObject {
request: URLRequest?,
response: URLResponse,
cookieStore: WKHTTPCookieStore,
canShowInWebView: Bool,
forceDownload: Bool
canShowInWebView: Bool
) {
guard let request = request else {
return nil
Expand All @@ -71,7 +70,7 @@ class DownloadHelper: NSObject {
let isAttachment =
contentDisposition?.starts(with: "attachment") ?? (mimeType == MIMEType.octetStream)

guard isAttachment || !canShowInWebView || forceDownload else {
guard isAttachment || !canShowInWebView else {
return nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,10 @@ class LivePlaylistWebLoader: UIView, PlaylistWebLoader {
static let userScript: WKUserScript? = nil
static let playlistProcessDocumentLoad = PlaylistScriptHandler.playlistProcessDocumentLoad

func userContentController(
_ userContentController: WKUserContentController,
didReceiveScriptMessage message: WKScriptMessage,
replyHandler: (Any?, String?) -> Void
func tab(
_ tab: Tab,
receivedScriptMessage message: WKScriptMessage,
replyHandler: @escaping (Any?, String?) -> Void
) {
if !verifyMessage(message: message) {
assertionFailure("Missing required security token.")
Expand Down
44 changes: 23 additions & 21 deletions ios/brave-ios/Sources/Brave/Frontend/Browser/Tab.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ protocol TabContentScript: TabContentScriptLoader {
func verifyMessage(message: WKScriptMessage) -> Bool
func verifyMessage(message: WKScriptMessage, securityToken: String) -> Bool

func userContentController(
_ userContentController: WKUserContentController,
didReceiveScriptMessage message: WKScriptMessage,
@MainActor func tab(
_ tab: Tab,
receivedScriptMessage message: WKScriptMessage,
replyHandler: @escaping (Any?, String?) -> Void
)
}
Expand Down Expand Up @@ -358,7 +358,7 @@ class Tab: NSObject {

// There is no 'available macro' on props, we currently just need to store ownership.
lazy var contentBlocker = ContentBlockerHelper(tab: self)
lazy var requestBlockingContentHelper = RequestBlockingContentScriptHandler(tab: self)
let requestBlockingContentHelper = RequestBlockingContentScriptHandler()

/// The last title shown by this tab. Used by the tab tray to show titles for zombie tabs.
var lastTitle: String?
Expand Down Expand Up @@ -398,7 +398,7 @@ class Tab: NSObject {
// If this tab has been opened from another, its parent will point to the tab from which it was opened
weak var parent: Tab?

fileprivate var contentScriptManager = TabContentScriptManager()
fileprivate let contentScriptManager = TabContentScriptManager()
private var userScripts = Set<UserScriptManager.ScriptType>()
private var customUserScripts = Set<UserScriptType>()

Expand Down Expand Up @@ -450,8 +450,10 @@ class Tab: NSObject {
tabGeneratorAPI: BraveTabGeneratorAPI? = nil
) {
self.configuration = configuration
self.favicon = Favicon.default
self.id = id
self.type = type

self.favicon = Favicon.default
rewardsId = UInt32.random(in: 1...UInt32.max)
nightMode = Preferences.General.nightModeEnabled.value
_syncTab = tabGeneratorAPI?.createBraveSyncTab(isOffTheRecord: type == .private)
Expand All @@ -465,7 +467,8 @@ class Tab: NSObject {
}

super.init()
self.type = type

self.contentScriptManager.tab = self
}

weak var navigationDelegate: WKNavigationDelegate? {
Expand Down Expand Up @@ -625,7 +628,7 @@ class Tab: NSObject {
}

func deleteWebView() {
contentScriptManager.uninstall(from: self)
contentScriptManager.uninstall()

if let webView = webView {
webView.removeObserver(self, forKeyPath: KVOConstants.url.keyPath)
Expand Down Expand Up @@ -1053,30 +1056,29 @@ extension Tab: TabWebViewDelegate {

private class TabContentScriptManager: NSObject, WKScriptMessageHandlerWithReply {
fileprivate var helpers = [String: TabContentScript]()
weak var tab: Tab?

func uninstall(from tab: Tab) {
func uninstall() {
helpers.forEach {
let name = type(of: $0.value).messageHandlerName
tab.webView?.configuration.userContentController.removeScriptMessageHandler(forName: name)
tab?.webView?.configuration.userContentController.removeScriptMessageHandler(forName: name)
}
}

@objc func userContentController(
func userContentController(
_ userContentController: WKUserContentController,
didReceive message: WKScriptMessage,
replyHandler: @escaping (Any?, String?) -> Void
) {
for helper in helpers.values {
let scriptMessageHandlerName = type(of: helper).messageHandlerName
if scriptMessageHandlerName == message.name {
helper.userContentController(
userContentController,
didReceiveScriptMessage: message,
replyHandler: replyHandler
)
return
}
guard let tab,
let helper = helpers.values.first(where: {
type(of: $0).messageHandlerName == message.name
})
else {
replyHandler(nil, nil)
return
}
helper.tab(tab, receivedScriptMessage: message, replyHandler: replyHandler)
}

func addContentScript(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class ReadabilityOperation: Operation {
self.tab.createWebview()
self.tab.navigationDelegate = self

let readerMode = ReaderModeScriptHandler(tab: self.tab)
let readerMode = ReaderModeScriptHandler()
readerMode.delegate = self
self.tab.addContentScript(
readerMode,
Expand Down
Loading

0 comments on commit a6857a4

Please sign in to comment.