31 Commits

Author SHA1 Message Date
797c4c7c52 darkmode css: remove em from reinvert list 2025-09-18 08:52:15 -07:00
6cc4694e1e attempt to fix stale tabs 2025-09-06 22:56:51 -07:00
334703ec43 Obscure mail spi 2025-05-05 19:05:49 -07:00
6301c40c59 Obscure WebKit SPI 2025-05-05 19:01:46 -07:00
8fe8426cc2 Delete web process bundle in favor of custom scheme handler 2025-05-05 18:14:46 -07:00
a2e29abf19 Fixup for distribution 2025-04-11 19:53:02 -07:00
2f4b3c64fe Move off of internal SDK, copy webkit spis from opensource 2025-04-11 18:27:59 -07:00
James Magahern
177db26b69 Implements zoom in/out keyboard shortcuts 2024-10-17 13:38:41 -07:00
0fd466d86d Adds keyboard shortcuts for changing script policy 2024-08-05 18:09:04 -07:00
69aa02e303 Resolves "New Tab" bug after web content process jettison 2024-08-05 17:36:59 -07:00
James Magahern
29057c8024 History menu improvements 2024-07-31 17:53:23 -07:00
a0056af8b1 Update for iOS 17. 2024-07-29 19:21:51 -07:00
James Magahern
6dccb25b3e TitlebarView: move to drag api 2024-05-10 17:01:14 -07:00
James Magahern
eec57f5f31 History UI improvements 2023-09-26 16:23:35 -07:00
d9fa5adf00 Adds README and screenshot 2023-09-17 20:30:21 -07:00
James Magahern
a4c6caeb8e Another attempt to fix empty URL bar 2023-08-10 19:52:59 -07:00
James Magahern
3f5d608908 Even better AI generated icon 2023-04-19 14:39:06 -07:00
James Magahern
99bd3af187 Fix warnings 2023-04-19 14:33:17 -07:00
James Magahern
98dfd85781 Small Settings QOL improvements 2023-04-19 14:30:06 -07:00
James Magahern
6a187b0df3 Update icon to use Midjourney generated one 2023-04-19 11:45:21 -07:00
James Magahern
dca5aca1ce UIGraphicsImageContext: both dimensions must be > 0 2023-04-19 11:40:57 -07:00
James Magahern
f8d19414d5 Avoid generating zero size bitmaps 2023-04-14 19:37:31 -07:00
James Magahern
748023d330 Adds history menu 2023-01-27 13:46:23 -08:00
6f41caff62 HistoryView: Compact UI for phones 2023-01-25 16:13:09 -08:00
34ca35ea5a HistoryView: Adds ability to delete history items 2023-01-25 15:04:58 -08:00
James Magahern
53efb5389e Adds history browser view 2023-01-20 17:28:15 -08:00
James Magahern
f374f3ebe8 Tweak autocomplete query a bit 2023-01-20 16:20:36 -08:00
James Magahern
836daee5a3 Fix find and replace 2023-01-11 13:20:36 -08:00
12e2d82009 Attempt to fix blank URL bar bug 2022-10-11 15:04:59 -07:00
6be801420c iOS 16 API updates 2022-10-11 15:04:37 -07:00
James Magahern
75153d1c4a Settings: Catalyst: adjust slightly the header labels 2022-08-22 17:43:04 -07:00
110 changed files with 3596 additions and 713 deletions

View File

@@ -32,6 +32,28 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
return UISceneConfiguration(name: "Browser", sessionRole: connectingSceneSession.role)
}
private func historyMenu() -> UIMenu {
let historyItems = BrowserHistory.shared.allHistory(limit: 50).map { item in
let title = ((item.title.count > 0) ? item.title : item.url.absoluteString)
.middleTruncatedString(maximumLength: 85)
return UIAction(title: title) { action in
UIApplication.shared.sendAction(#selector(ShortcutResponder.handleOpenURL), to: nil, from: action, for: OpenURLEvent(url: item.url))
}
}
return UIMenu(title: "History", children: [
UIKeyCommand(
modifiers: [ .command ],
input: "y",
title: "Show All History…",
action: #selector(ShortcutResponder.showHistory)
),
UIMenu(options: .displayInline, children: historyItems)
])
}
override var keyCommands: [UIKeyCommand]? {
get { KeyboardShortcuts.allKeyCommands() }
}
@@ -68,6 +90,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
// Go
builder.insertSibling(UIMenu(title: "Go", children: KeyboardShortcuts.menu(for: .go)), beforeMenu: .view)
// History
builder.insertSibling(historyMenu(), beforeMenu: .view)
// View
builder.replaceChildren(ofMenu: .view) { children in
KeyboardShortcuts.menu(for: .view) + children

View File

@@ -7,9 +7,58 @@
import Foundation
import CoreData
import Combine
class BrowserHistory
{
class ViewModel: NSObject, ObservableObject, NSFetchedResultsControllerDelegate {
@Published var searchQuery: String = ""
@Published private(set) var historyItems: [HistoryItem] = []
fileprivate let historyController: BrowserHistory
fileprivate var searchQueryObserver: AnyCancellable? = nil
fileprivate var fetchedResultsController: NSFetchedResultsController<HistoryItemEntity> {
didSet { fetchedResultsController.delegate = self; performInitialFetch() }
}
fileprivate init(fetchedResultsController: NSFetchedResultsController<HistoryItemEntity>, historyController: BrowserHistory) {
self.fetchedResultsController = fetchedResultsController
self.historyController = historyController
super.init()
searchQueryObserver = $searchQuery.sink { [unowned self] newValue in
self.fetchedResultsController = historyController.fetchRequestController(forQuery: newValue)
}
}
public func item(forIdentifier identifier: HistoryItem.ID) -> HistoryItem? {
if let object = fetchedResultsController.managedObjectContext.object(with: identifier) as? HistoryItemEntity {
return HistoryItem(entity: object)
}
return nil
}
public func deleteItems(_ items: Set<HistoryItem.ID>) {
items.forEach { identifier in
historyController.deleteItem(withIdentifier: identifier)
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
if let objects = controller.fetchedObjects as? [HistoryItemEntity] {
self.historyItems = objects.map { HistoryItem(entity: $0) }
}
}
fileprivate func performInitialFetch() {
try? fetchedResultsController.performFetch()
if let objects = fetchedResultsController.fetchedObjects {
self.historyItems = objects.map { HistoryItem(entity: $0) }
}
}
}
static public let shared = BrowserHistory()
lazy fileprivate var persistentContainer: NSPersistentContainer = {
@@ -35,12 +84,43 @@ class BrowserHistory
let nserror = error as NSError
fatalError("Failed saving persistent entity to store: \(nserror), \(nserror.userInfo)")
}
UIMenuSystem.main.setNeedsRebuild()
}
public func allHistory() -> [HistoryItem] {
let dataContext = persistentContainer.viewContext
public func viewModel(forFilterString filterString: String? = nil, limit: Int = 500) -> ViewModel {
let resultsController = fetchRequestController(forQuery: filterString, limit: limit)
return ViewModel(fetchedResultsController: resultsController, historyController: self)
}
let fetchRequest: NSFetchRequest<HistoryItemEntity> = HistoryItemEntity.fetchRequest()
public func historyItem(forIdentifier: HistoryItem.ID) -> HistoryItem? {
if let entity = try? persistentContainer.viewContext.existingObject(with: forIdentifier) as? HistoryItemEntity {
return HistoryItem(entity: entity)
}
return nil
}
public func deleteItem(withIdentifier identifier: HistoryItem.ID) {
let dataContext = persistentContainer.viewContext
if let object = try? dataContext.existingObject(with: identifier) {
dataContext.delete(object)
try? dataContext.save()
}
}
public func clearAllHistory() {
let dataContext = persistentContainer.viewContext
let fetchRequest: NSFetchRequest<NSFetchRequestResult> = HistoryItemEntity.fetchRequest()
let request = NSBatchDeleteRequest(fetchRequest: fetchRequest)
do { try dataContext.execute(request) }
catch { print("Error clearing history: \(error.localizedDescription)") }
}
public func allHistory(filteredBy filterString: String? = nil, limit: Int = 500) -> [HistoryItem] {
let dataContext = persistentContainer.viewContext
let fetchRequest = fetchRequest(forStringContaining: filterString, limit: limit)
let entities: [HistoryItemEntity] = (try? dataContext.fetch(fetchRequest)) ?? []
return entities.map { (entity) -> HistoryItem in
@@ -52,7 +132,11 @@ class BrowserHistory
let dataContext = persistentContainer.viewContext
let fetchRequest: NSFetchRequest<HistoryItemEntity> = HistoryItemEntity.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "host CONTAINS %@ OR title contains %@", matching, matching)
fetchRequest.predicate = NSPredicate(format: """
host CONTAINS[cd] %@
OR title CONTAINS[cd] %@
OR url ENDSWITH[cd] %@
""", matching, matching, matching)
fetchRequest.fetchLimit = 200
fetchRequest.sortDescriptors = [ NSSortDescriptor(key: "visitCount", ascending: false) ]
@@ -85,6 +169,35 @@ class BrowserHistory
}
}
extension BrowserHistory
{
fileprivate func fetchRequestController(forQuery query: String? = nil, limit: Int = 500) -> NSFetchedResultsController<HistoryItemEntity> {
let fetchRequest = fetchRequest(forStringContaining: query, limit: limit)
return NSFetchedResultsController(fetchRequest: fetchRequest,
managedObjectContext: persistentContainer.viewContext,
sectionNameKeyPath: nil, cacheName: nil)
}
fileprivate func fetchRequest(forStringContaining filterString: String? = nil, limit: Int = 500) -> NSFetchRequest<HistoryItemEntity> {
let fetchRequest: NSFetchRequest<HistoryItemEntity> = HistoryItemEntity.fetchRequest()
fetchRequest.fetchLimit = limit
fetchRequest.sortDescriptors = [
// Sort by date
NSSortDescriptor(keyPath: \HistoryItemEntity.lastVisited, ascending: false)
]
if let filterString, filterString.count > 0 {
fetchRequest.predicate = NSPredicate(format: """
host CONTAINS[cd] %@
OR title CONTAINS[cd] %@
OR url CONTAINS[cd] %@
""", filterString, filterString, filterString)
}
return fetchRequest
}
}
extension URL
{
public func topLevelURL() -> URL {

View File

@@ -5,17 +5,28 @@
// Created by James Magahern on 8/14/20.
//
import CoreData
import Foundation
struct HistoryItem: Hashable
struct HistoryItem: Hashable, Identifiable
{
var url: URL
var title: String
var lastVisited: Date
var id: NSManagedObjectID
init(entity: HistoryItemEntity) {
self.url = entity.url ?? URL(string: "about:blank")!
self.lastVisited = entity.lastVisited ?? Date()
self.title = entity.title ?? ""
self.id = entity.objectID
}
// For testing/previews
public init(url: URL, title: String, lastVisited: Date) {
self.url = url
self.title = title
self.lastVisited = lastVisited
self.id = NSManagedObjectID()
}
}

View File

@@ -31,7 +31,8 @@ class ResourcePolicyManager: NSObject, SBRResourceOriginPolicyDataSource
func allowedOriginsForScriptResources() -> Set<String> { allowedOriginSet }
func scriptPolicyTypeByOrigin() -> [String : NSNumber] {
return scriptPolicies.mapValues { NSNumber(integerLiteral: $0.rawValue) }
let types = scriptPolicies.mapValues { NSNumber(integerLiteral: $0.rawValue) }
return types
}
private lazy var scriptPolicies: Dictionary<String, ScriptPolicy.PolicyType> = {

View File

@@ -98,6 +98,7 @@ class BrowserView: UIView
}
}(animationCurve)
toolbarView?.layoutLatch.deactivate()
keyboardLayoutOffset = bounds.height - keyboardEndFrame.minY
UIView.animate(withDuration: animationDuration, delay: 0.0, options: animationOptions, animations: { self.layoutIfNeeded() }, completion: nil)
}

View File

@@ -94,11 +94,11 @@ extension BrowserViewController: ShortcutResponder
}
func goBack(_ sender: Any?) {
tab.webView.goBack()
currentTab.webView.goBack()
}
func goForward(_ sender: Any?) {
tab.webView.goForward()
currentTab.webView.goForward()
}
func createTab(_ sender: Any?) {
@@ -106,24 +106,24 @@ extension BrowserViewController: ShortcutResponder
}
func previousTab(_ sender: Any?) {
if let tabIndex = tabController.tabs.firstIndex(of: self.tab) {
if let tabIndex = tabController.tabs.firstIndex(of: self.currentTab) {
if tabIndex - 1 >= 0 {
self.tab = tabController.tabs[tabIndex - 1]
self.currentTab = tabController.tabs[tabIndex - 1]
}
}
}
func nextTab(_ sender: Any?) {
if let tabIndex = tabController.tabs.firstIndex(of: self.tab) {
if let tabIndex = tabController.tabs.firstIndex(of: self.currentTab) {
if tabIndex + 1 < tabController.tabs.count {
self.tab = tabController.tabs[tabIndex + 1]
self.currentTab = tabController.tabs[tabIndex + 1]
}
}
}
func closeTab(_ sender: Any?) {
if tabController.tabs.count > 1 {
tabController.closeTab(self.tab)
tabController.closeTab(self.currentTab)
} else {
#if targetEnvironment(macCatalyst)
if let originWindowScene = self.view.window?.windowScene {
@@ -144,18 +144,30 @@ extension BrowserViewController: ShortcutResponder
webView.reload()
}
func stop(_ sender: Any?) {
webView.stopLoading()
}
override func increaseSize(_ sender: Any?) {
tab.webView._viewScale += 0.10
currentTab.webView._viewScale += 0.10
}
override func decreaseSize(_ sender: Any?) {
tab.webView._viewScale -= 0.10
currentTab.webView._viewScale -= 0.10
}
func zoomToActualSize(_ sender: Any?) {
currentTab.webView._viewScale = 1.0
}
func showPreferences(_ sender: Any?) {
showSettingsWindow()
}
func showHistory(_ sender: Any?) {
showHistoryWindow()
}
func toggleDarkMode(_ sender: Any?) {
self.darkModeEnabled = !self.darkModeEnabled
}
@@ -163,4 +175,50 @@ extension BrowserViewController: ShortcutResponder
func openInReaderMode(_ sender: Any?) {
showReaderWindow()
}
func handleOpenURL(_ sender: Any?, forEvent event: OpenURLEvent?) {
guard let event else { return }
if currentTab.url == nil {
currentTab.beginLoadingURL(event.url)
} else {
createNewTab(withURL: event.url)
}
}
func raiseScriptPolicyRestriction(_ sender: Any?) {
guard let hostOrigin = currentTab.webView.url?.securityOrigin else { return }
let currentPolicy = policyManager.scriptPolicy(forOrigin: hostOrigin)
policyManager.setScriptPolicyType(currentPolicy.policyType--, forOrigin: hostOrigin)
didChangeScriptPolicy()
}
func lowerScriptPolicyRestriction(_ sender: Any?) {
guard let hostOrigin = currentTab.webView.url?.securityOrigin else { return }
let currentPolicy = policyManager.scriptPolicy(forOrigin: hostOrigin)
policyManager.setScriptPolicyType(currentPolicy.policyType++, forOrigin: hostOrigin)
didChangeScriptPolicy()
}
}
extension ScriptPolicy.PolicyType {
static postfix func ++ (obj: ScriptPolicy.PolicyType) -> ScriptPolicy.PolicyType {
switch obj {
case .alpha: .bravo
case .bravo: .charlie
case .charlie: .delta
case .delta: .echo
default: obj
}
}
static postfix func -- (obj: ScriptPolicy.PolicyType) -> ScriptPolicy.PolicyType {
switch obj {
case .bravo: .alpha
case .charlie: .bravo
case .delta: .charlie
case .echo: .delta
default: obj
}
}
}

View File

@@ -10,35 +10,15 @@ import WebKit
extension BrowserViewController: WKNavigationDelegate, WKUIDelegate
{
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
if let tab = tabController.tab(forWebView: webView) {
// We're alive!
tab.contentProcessTerminated = false
tab.loadError = nil
// Check to make sure we have connected to the web content process
if !tab.bridge.webContentProcessConnected {
// This means we started loading a page but the web content process hasn't loaded, which means
// scripts are not getting blocked.
// If you're ad-hoc signing this, you'll need to disable library validation:
// sudo defaults write /Library/Preferences/com.apple.security.libraryvalidation DisableLibraryValidation -bool YES
DispatchQueue.main.async { [unowned self] in
// Stop loading now
webView.stopLoading()
// Show an alert
let alert = UIAlertController(title: "Web Process Not Loaded",
message: "The web content process never contacted the host application",
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { _ in
alert.dismiss(animated: true, completion: nil)
}))
present(alert, animated: true, completion: nil)
}
}
// Reset tracking this
tab.allowedScriptOrigins.removeAll()
tab.blockedScriptOrigins.removeAll()
currentTab.allowedScriptOrigins.removeAll()
currentTab.blockedScriptOrigins.removeAll()
updateScriptBlockerButton()
// Blur url bar if applicable
@@ -48,7 +28,7 @@ extension BrowserViewController: WKNavigationDelegate, WKUIDelegate
if let url = webView.url {
// Start requesting favicon
tab.updateFaviconForURL(url)
currentTab.updateFaviconForURL(url)
}
}
@@ -56,7 +36,7 @@ extension BrowserViewController: WKNavigationDelegate, WKUIDelegate
// We got rugged!!!!!! Update the favicon again.
if let url = webView.url {
// Start requesting favicon
tab.updateFaviconForURL(url)
currentTab.updateFaviconForURL(url)
}
}
@@ -90,7 +70,7 @@ extension BrowserViewController: WKNavigationDelegate, WKUIDelegate
return
}
var allowJavaScript = tab.javaScriptEnabled
var allowJavaScript = currentTab.javaScriptEnabled
if !allowJavaScript, let host = navigationAction.request.url?.host {
// Check origin policy
allowJavaScript = policyManager.scriptPolicy(forOrigin: host).allowsEmbeddedJavaScript()
@@ -101,7 +81,7 @@ extension BrowserViewController: WKNavigationDelegate, WKUIDelegate
if let url = navigationAction.request.url,
let redirectedURL = Settings.shared.redirectRule(for: url)
{
tab.beginLoadingURL(redirectedURL)
currentTab.beginLoadingURL(redirectedURL)
decisionHandler(.cancel, preferences)
} else {
decisionHandler(.allow, preferences)
@@ -109,17 +89,21 @@ extension BrowserViewController: WKNavigationDelegate, WKUIDelegate
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
if webView == tab.webView {
tab.loadError = error
if webView == currentTab.webView {
currentTab.loadError = error
}
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
if webView == tab.webView {
tab.loadError = error
if webView == currentTab.webView {
currentTab.loadError = error
}
}
func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
tabController.tab(forWebView: webView)?.contentProcessTerminated = true
}
// MARK: WKUIDelegate
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView?
@@ -127,7 +111,7 @@ extension BrowserViewController: WKNavigationDelegate, WKUIDelegate
let newTab = tabController.createNewTab(url: nil, webViewConfiguration: configuration)
newTab.webView.load(navigationAction.request)
self.tab = newTab
self.currentTab = newTab
return newTab.webView
}

View File

@@ -13,8 +13,8 @@ import UniformTypeIdentifiers
class BrowserViewController: UIViewController
{
let browserView = BrowserView()
var tab: Tab { didSet { didChangeTab(tab) } }
var webView: WKWebView { tab.webView }
var currentTab: Tab { didSet { didChangeTab(currentTab) } }
var webView: WKWebView { currentTab.webView }
internal let tabController = TabController()
internal let tabBarViewController: TabBarViewController
@@ -42,9 +42,9 @@ class BrowserViewController: UIViewController
static let longPressWindowButtonToMakeNewTab: Bool = false
internal var darkModeEnabled: Bool {
get { tab.bridge.darkModeEnabled }
get { currentTab.bridge.darkModeEnabled }
set {
tab.bridge.darkModeEnabled = newValue
currentTab.bridge.darkModeEnabled = newValue
toolbarController.darkModeEnabled = newValue
}
}
@@ -60,7 +60,7 @@ class BrowserViewController: UIViewController
internal var changingFocusToAutocompleteController = false
init() {
self.tab = tabController.tabs.first!
self.currentTab = tabController.tabs.first!
self.tabBarViewController = TabBarViewController(tabController: tabController)
super.init(nibName: nil, bundle: nil)
@@ -70,7 +70,7 @@ class BrowserViewController: UIViewController
addChild(findOnPageController)
addChild(tabBarViewController)
didChangeTab(tab)
didChangeTab(currentTab)
}
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
@@ -114,12 +114,12 @@ class BrowserViewController: UIViewController
// Script button
toolbarController.scriptControllerIconView.addAction(UIAction(handler: { [unowned self] action in
let hostOrigin = self.webView.url?.host ?? ""
let loadedScripts = self.tab.allowedScriptOrigins.union(self.tab.blockedScriptOrigins)
let hostOrigin = self.webView.url?.securityOrigin ?? ""
let loadedScripts = currentTab.allowedScriptOrigins.union(currentTab.blockedScriptOrigins)
let scriptViewController = ScriptPolicyViewController(policyManager: self.policyManager,
hostOrigin: hostOrigin,
loadedScripts: loadedScripts,
scriptsAllowedForTab: self.tab.javaScriptEnabled)
scriptsAllowedForTab: currentTab.javaScriptEnabled)
scriptViewController.delegate = self
let navController = UINavigationController(rootViewController: scriptViewController)
@@ -141,7 +141,7 @@ class BrowserViewController: UIViewController
tabPickerController.delegate = self
tabPickerController.title = "Tabs"
tabPickerController.tabBarItem.image = UIImage(systemName: "rectangle.on.rectangle")
tabPickerController.selectedTabIdentifier = self.tab.identifier
tabPickerController.selectedTabIdentifier = currentTab.identifier
tabPickerController.tabObserver = tabController.$tabs
.receive(on: RunLoop.main)
.sink(receiveValue: { (newTabs: [Tab]) in
@@ -207,7 +207,7 @@ class BrowserViewController: UIViewController
// Error button
toolbarController.urlBar.errorButton.addAction(UIAction(handler: { [unowned self] _ in
let alert = UIAlertController(title: "Error", message: self.tab.loadError?.localizedDescription, preferredStyle: .actionSheet)
let alert = UIAlertController(title: "Error", message: currentTab.loadError?.localizedDescription, preferredStyle: .actionSheet)
alert.popoverPresentationController?.sourceView = self.toolbarController.urlBar.errorButton
alert.addAction(UIAlertAction(title: "Reload", style: .destructive, handler: { _ in
@@ -240,7 +240,7 @@ class BrowserViewController: UIViewController
// Font size adjust
toolbarController.urlBar.documentButton.addAction(UIAction(handler: { [unowned self] _ in
let documentControls = DocumentControlViewController(darkModeEnabled: tab.bridge.darkModeEnabled)
let documentControls = DocumentControlViewController(darkModeEnabled: currentTab.bridge.darkModeEnabled)
documentControls.modalPresentationStyle = .popover
documentControls.popoverPresentationController?.permittedArrowDirections = [ .down, .up ]
documentControls.popoverPresentationController?.sourceView = toolbarController.urlBar.documentButton
@@ -250,28 +250,30 @@ class BrowserViewController: UIViewController
numberFormatter.numberStyle = .percent
let label = documentControls.fontSizeAdjustView.labelView
label.text = numberFormatter.string(for: tab.webView._viewScale)
label.text = numberFormatter.string(for: currentTab.webView._viewScale)
// Font size adjust
documentControls.fontSizeAdjustView.decreaseSizeButton.addAction(UIAction(handler: { [unowned self] sender in
self.decreaseSize(sender)
label.text = numberFormatter.string(for: tab.webView._viewScale)
label.text = numberFormatter.string(for: currentTab.webView._viewScale)
}), for: .touchUpInside)
documentControls.fontSizeAdjustView.increaseSizeButton.addAction(UIAction(handler: { [unowned self] sender in
self.increaseSize(sender)
label.text = numberFormatter.string(for: tab.webView._viewScale)
label.text = numberFormatter.string(for: currentTab.webView._viewScale)
}), for: .touchUpInside)
// Find on page
documentControls.findOnPageControlView.addAction(UIAction(handler: { [unowned self] _ in
documentControls.dismiss(animated: true, completion: nil)
documentControls.dismiss(animated: true, completion: { [unowned self] in
// Needs to happen after dismissal, otherwise the find navigator will pick up the document
// controls as the divergent responder/deepest action responder (my bad...).
if FindOnPageViewController.isEnabled() {
browserView.setFindOnPageVisible(true, animated: true)
} else if #available(iOS 16.0, *) {
browserView.webView?._findInteraction.presentFindNavigatorShowingReplace(false)
browserView.webView?.findInteraction?.presentFindNavigator(showingReplace: false)
}
})
}), for: .touchUpInside)
// Navigation controls
@@ -331,6 +333,12 @@ class BrowserViewController: UIViewController
showShareSheetForCurrentURL(fromViewController: documentControls)
}, for: .touchUpInside)
// History
documentControls.historyView.addAction(UIAction { [unowned self] action in
documentControls.dismiss(animated: false, completion: nil)
showHistory(action)
}, for: .touchUpInside)
present(documentControls, animated: true, completion: nil)
}), for: .touchUpInside)
@@ -340,8 +348,8 @@ class BrowserViewController: UIViewController
.sink(receiveValue: { [unowned self] (activeTab: Int) in
if activeTab < tabController.tabs.count {
let tab = tabController.tabs[activeTab]
if self.tab != tab {
self.tab = tab
if currentTab != tab {
currentTab = tab
}
}
@@ -349,6 +357,11 @@ class BrowserViewController: UIViewController
self.updateTabBarVisibility()
})
registerForTraitChanges([UITraitHorizontalSizeClass.self]) { [weak self] (traitEnvironment: Self, previousTraitCollection) in
guard let self else { return }
toolbarController.reconfigureButtons(for: traitCollection.horizontalSizeClass)
}
self.view = browserView
}
@@ -362,7 +375,7 @@ class BrowserViewController: UIViewController
let shareableURL = ShareableURL(
url: url,
title: webView.title ?? url.absoluteString,
favicon: tab.favicon
favicon: currentTab.favicon
)
let activityController = UIActivityViewController(activityItems: [ shareableURL ], applicationActivities: nil)
@@ -436,21 +449,21 @@ class BrowserViewController: UIViewController
}
internal func showReaderWindow() {
tab.bridge.parseDocumentForReaderMode { string in
currentTab.bridge.parseDocumentForReaderMode { [currentTab] string in
DispatchQueue.main.async {
if self.traitCollection.userInterfaceIdiom == .phone {
let readableViewController = ReaderViewController(readableHTMLString: string, baseURL: self.tab.bridge.webView.url)
readableViewController.title = self.tab.bridge.webView.title
readableViewController.darkModeEnabled = self.tab.bridge.darkModeEnabled
let readableViewController = ReaderViewController(readableHTMLString: string, baseURL: currentTab.bridge.webView.url)
readableViewController.title = currentTab.bridge.webView.title
readableViewController.darkModeEnabled = currentTab.bridge.darkModeEnabled
readableViewController.delegate = self
let navigationController = UINavigationController(rootViewController: readableViewController)
self.present(navigationController, animated: true, completion: nil)
} else {
let userActivity = NSUserActivity(activityType: SessionActivityType.ReaderWindow.rawValue)
userActivity.title = self.tab.title
userActivity.title = currentTab.title
userActivity.userInfo = [
ReaderUserActivityKeys.baseURL.rawValue : self.tab.bridge.webView.url ?? NSNull(),
ReaderUserActivityKeys.baseURL.rawValue : currentTab.bridge.webView.url ?? NSNull(),
ReaderUserActivityKeys.htmlString.rawValue : string,
]
let requestOptions = UIWindowScene.ActivationRequestOptions()
@@ -461,8 +474,41 @@ class BrowserViewController: UIViewController
}
}
internal func showHistoryWindow() {
let historyViewController = HistoryBrowserViewController { [unowned self] url in
if currentTab.url == nil {
currentTab.beginLoadingURL(url)
} else {
createNewTab(withURL: url)
}
presentedViewController?.dismiss(animated: true)
}
historyViewController.title = "History"
historyViewController.navigationItem.rightBarButtonItem = UIBarButtonItem(systemItem: .done, primaryAction: UIAction { _ in
// xxx: This is not the SwiftUI-y way to do this.
historyViewController.dismiss(animated: true)
})
historyViewController.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Clear", primaryAction: UIAction { [unowned self] action in
let alertController = UIAlertController(title: "Clear History", message: "Are you sure you want to clear all history?", preferredStyle: .actionSheet)
alertController.addAction(UIAlertAction(title: "Clear", style: .destructive, handler: { [unowned self] _ in
BrowserHistory.shared.clearAllHistory()
presentedViewController?.dismiss(animated: true)
}))
alertController.addAction(UIAlertAction(title: "Cancel", style: .cancel))
alertController.popoverPresentationController?.sourceItem = action.presentationSourceItem
presentedViewController?.present(alertController, animated: true)
})
let navigationController = UINavigationController(rootViewController: historyViewController)
present(navigationController, animated: true)
}
internal func updateLoadProgress(forWebView webView: WKWebView) {
if let loadError = tab.loadError {
if let loadError = currentTab.loadError {
toolbarController.urlBar.loadProgress = .error(error: loadError)
} else if webView.estimatedProgress == 1.0 {
toolbarController.urlBar.loadProgress = .complete
@@ -474,6 +520,8 @@ class BrowserViewController: UIViewController
}
internal func updateTitleAndURL(forWebView webView: WKWebView) {
guard let tab = tabController.tab(forWebView: webView) else { return }
if webView == browserView.webView {
browserView.titlebarView.setTitle(webView.title ?? "")
@@ -485,8 +533,7 @@ class BrowserViewController: UIViewController
}
// Figure out which tab this corresponds to
let tab = tabController.tabs.first { $0.webView == webView }
if let tab = tab, let tabIndex = tabController.tabs.firstIndex(of: tab) {
if let tabIndex = tabController.tabs.firstIndex(of: tab) {
tabBarViewController.tabBarView.reloadTab(atIndex: tabIndex)
}
}
@@ -496,9 +543,9 @@ class BrowserViewController: UIViewController
tabController.activeTabIndex = activeIndex
}
tab.delegate = self
currentTab.delegate = self
let webView = tab.webView
let webView = currentTab.webView
webView.allowsBackForwardNavigationGestures = true
webView.navigationDelegate = self
webView.uiDelegate = self
@@ -543,10 +590,23 @@ class BrowserViewController: UIViewController
updateScriptBlockerButton()
// Enforce dark mode setting
tab.bridge.darkModeEnabled = toolbarController.darkModeEnabled
currentTab.bridge.darkModeEnabled = toolbarController.darkModeEnabled
// Blur url bar, if applicable
toolbarController.urlBar.textField.resignFirstResponder()
// If this tab's web content process was jettisoned while in background,
// its current page may appear blank and url be nil. Proactively reload
// when the tab becomes active again to restore state.
if tab.contentProcessTerminated {
if webView.url != nil || tab.url != nil {
webView.reload()
} else if let home = tab.homeURL {
tab.beginLoadingURL(home)
} else {
webView.reload()
}
}
}
override func target(forAction action: Selector, withSender sender: Any?) -> Any? {
@@ -571,18 +631,23 @@ class BrowserViewController: UIViewController
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
becomeFirstResponder()
// If the app resumed and the current tab's web content process was
// terminated while in background, ensure we restore it now.
if currentTab.contentProcessTerminated {
if webView.url != nil || currentTab.url != nil {
webView.reload()
} else if let home = currentTab.homeURL {
currentTab.beginLoadingURL(home)
} else {
webView.reload()
}
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
// Not sure why this doesn't happen automatically...
toolbarController.traitCollectionDidChange(previousTraitCollection)
}
internal func updateScriptBlockerButton() {
var numBlockedScripts: Int = tab.blockedScriptOrigins.count
if tab.url != nil, tab.javaScriptEnabled == false {
var numBlockedScripts: Int = currentTab.blockedScriptOrigins.count
if currentTab.url != nil, currentTab.javaScriptEnabled == false {
// Because the page is blocked too, notify.
numBlockedScripts += 1
}
@@ -593,7 +658,7 @@ class BrowserViewController: UIViewController
}
let iconView = toolbarController.scriptControllerIconView
iconView.shieldsDown = tab.javaScriptEnabled
iconView.shieldsDown = currentTab.javaScriptEnabled
// iconView.setBlockedScriptsNumber(numBlockedScripts)
if let policy = policy {
@@ -608,7 +673,7 @@ class BrowserViewController: UIViewController
let newTab = tabController.createNewTab(url: url)
if !loadInBackground {
self.tab = newTab
currentTab = newTab
if url == nil && traitCollection.userInterfaceIdiom == .mac {
self.toolbarController.urlBar.textField.becomeFirstResponder()
@@ -616,7 +681,7 @@ class BrowserViewController: UIViewController
} else {
// Send this message to get it to load NOW, instead of waiting for it to show up
// in the view hierarchy.
tab.webView.didMoveToWindow()
currentTab.webView.didMoveToWindow()
// Update tab bar now
updateTabBarVisibility()
@@ -637,12 +702,12 @@ extension BrowserViewController: UIPopoverPresentationControllerDelegate
extension BrowserViewController: ScriptPolicyViewControllerDelegate
{
func didChangeScriptPolicy() {
tab.bridge.policyDataSourceDidChange()
currentTab.bridge.policyDataSourceDidChange()
webView.reload()
}
func setScriptsEnabledForTab(_ enabled: Bool) {
tab.javaScriptEnabled = enabled
currentTab.javaScriptEnabled = enabled
toolbarController.scriptControllerIconView.shieldsDown = enabled
}
}
@@ -650,7 +715,7 @@ extension BrowserViewController: ScriptPolicyViewControllerDelegate
extension BrowserViewController: AutocompleteViewControllerDelegate
{
func autocompleteController(_: AutocompleteViewController, didSelectHistoryItem item: HistoryItem) {
tab.beginLoadingURL(item.url)
currentTab.beginLoadingURL(item.url)
autocompleteViewController.view.isHidden = true
}
}
@@ -665,7 +730,7 @@ extension BrowserViewController: TabDelegate
extension BrowserViewController: TabPickerViewControllerDelegate
{
func tabPicker(_ picker: TabPickerViewController, createNewTabWithURL url: URL?) {
self.tab = tabController.createNewTab(url: url)
currentTab = tabController.createNewTab(url: url)
picker.dismiss(animated: true)
}
@@ -684,7 +749,7 @@ extension BrowserViewController: TabPickerViewControllerDelegate
guard let tab else { return }
self.tab = tab
currentTab = tab
picker.dismiss(animated: true, completion: nil)
}
@@ -694,7 +759,7 @@ extension BrowserViewController: TabPickerViewControllerDelegate
tabController.closeTab(tab)
// Dismiss picker if current tab is closed using the picker
if tab == self.tab {
if tab == currentTab {
picker.dismiss(animated: true, completion: nil)
}
}
@@ -728,10 +793,10 @@ extension BrowserViewController: UITextFieldDelegate
}
}
tab.beginLoadingURL(url)
currentTab.beginLoadingURL(url)
} else {
let searchURL = Settings.shared.searchProvider.provider().searchURLWithQuery(text)
tab.beginLoadingURL(searchURL)
currentTab.beginLoadingURL(searchURL)
}
textField.resignFirstResponder()
@@ -740,10 +805,6 @@ extension BrowserViewController: UITextFieldDelegate
return false
}
override func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
true
}
func textFieldDidEndEditing(_ textField: UITextField) {
if !changingFocusToAutocompleteController {
autocompleteViewController.view.isHidden = true
@@ -754,7 +815,7 @@ extension BrowserViewController: UITextFieldDelegate
extension BrowserViewController: ReaderViewControllerDelegate
{
func readerViewController(_ reader: ReaderViewController, didRequestNavigationToURL navigationURL: URL) {
tab.beginLoadingURL(navigationURL)
currentTab.beginLoadingURL(navigationURL)
}
}

View File

@@ -28,11 +28,17 @@ class GradientView: UIImageView
self.init(image: nil)
self.direction = direction
self.colors = colors
registerForTraitChanges([UITraitUserInterfaceStyle.self]) { [weak self] (traitEnvironment: Self, previousTraitCollection) in
self?.image = nil
self?.setNeedsLayout()
}
}
private func gradientImage(forSize size: CGSize) -> UIImage? {
var image: UIImage? = nil
guard size.width > .leastNonzeroMagnitude && size.height > .leastNonzeroMagnitude else { return nil }
var image: UIImage? = nil
UIGraphicsBeginImageContext(size)
if let context = UIGraphicsGetCurrentContext() {
let gradientColorsArray = self.colors.map { $0.cgColor }
@@ -69,12 +75,4 @@ class GradientView: UIImageView
generatedImageSize = bounds.size
}
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
// Regenerate image
image = nil
setNeedsLayout()
}
}

View File

@@ -46,6 +46,8 @@ class ReliefButton: UIButton
}
})
self.imageView?.contentMode = .scaleAspectFit
shadowView.alpha = 0.28
shadowView.backgroundColor = UIColor(white: 0.0, alpha: 1.0)
shadowView.isUserInteractionEnabled = false
@@ -67,12 +69,14 @@ class ReliefButton: UIButton
backgroundView.layer.rasterizationScale = UIScreen.main.scale
addSubview(backgroundView)
traitCollectionDidChange(nil)
registerForTraitChanges([UITraitUserInterfaceStyle.self], handler: handleTraitCollectionChange)
pointerStyleProvider = { (button, pointerEffect, pointerShape) -> UIPointerStyle? in
let preview = UITargetedPreview(view: button)
return UIPointerStyle(effect: .lift(preview), shape: pointerShape)
}
handleTraitCollectionChange(self, previousCollection: nil)
}
required init?(coder: NSCoder) {
@@ -97,7 +101,7 @@ class ReliefButton: UIButton
return inverted ? colors.reversed() : colors
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
private func handleTraitCollectionChange(_ environment: UITraitEnvironment, previousCollection: UITraitCollection?) {
setBackgroundInverted(isHighlighted)
backgroundView.layer.borderColor = { traitCollection -> UIColor in
if traitCollection.userInterfaceStyle == .dark {
@@ -105,7 +109,7 @@ class ReliefButton: UIButton
} else {
return .white
}
}(traitCollection).cgColor
} (traitCollection).cgColor
}
internal func setBackgroundInverted(_ inverted: Bool) {
@@ -132,8 +136,6 @@ class ReliefButton: UIButton
}
override func layoutSubviews() {
self.imageView?.contentMode = .scaleAspectFit
super.layoutSubviews()
sendSubviewToBack(backgroundView)

View File

@@ -103,9 +103,16 @@ class DocumentControlItemView: UIControl
separatorView.isHidden = !drawsBottomSeparator
}
override func setTracking(_ tracking: Bool) {
super.setTracking(tracking)
highlightView.isHidden = !tracking
override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
super.beginTracking(touch, with: event)
highlightView.isHidden = false
return true
}
override func endTracking(_ touch: UITouch?, with event: UIEvent?) {
super.endTracking(touch, with: event)
highlightView.isHidden = true
}
public func title(_ title: String) -> Self {

View File

@@ -20,6 +20,7 @@ class DocumentControlViewController: UIViewController
let archiveView = DocumentControlItemView().title("Archive.today") .symbol("shippingbox")
let emailView = DocumentControlItemView().title("Email") .symbol("envelope")
let sharingView = DocumentControlItemView().title("Share") .symbol("square.and.arrow.up")
let historyView = DocumentControlItemView().title("History") .symbol("clock.arrow.circlepath")
let darkModeView = DocumentControlItemView().title("Dark Mode")
var observations: [NSKeyValueObservation] = []
@@ -46,6 +47,7 @@ class DocumentControlViewController: UIViewController
documentControlsView.stackView.addArrangedSubview(darkModeView)
documentControlsView.stackView.addArrangedSubview(readabilityView)
documentControlsView.stackView.addArrangedSubview(archiveView)
documentControlsView.stackView.addArrangedSubview(historyView)
documentControlsView.stackView.addArrangedSubview(settingsView)

View File

@@ -41,7 +41,7 @@ class FindOnPageViewController: UIViewController, _WKFindDelegate
findOnPageView.textField.addAction(UIAction(handler: { [unowned self] _ in
self.findString = findOnPageView.textField.text
webView?._find(self.findString, options: self.findOptions, maxCount: self.maxCount)
webView?._find(self.findString, options: self.findOptions, maxCount: UInt(self.maxCount))
}), for: .editingChanged)
findOnPageView.prevResultButton.addAction(UIAction(handler: { [unowned self] _ in
@@ -82,24 +82,20 @@ class FindOnPageViewController: UIViewController, _WKFindDelegate
@objc
override func findNext(_ sender: Any?) {
webView?._find(self.findString, options: self.findOptions, maxCount: self.maxCount)
webView?._find(self.findString, options: self.findOptions, maxCount: UInt(self.maxCount))
}
@objc
override func findPrevious(_ sender: Any?) {
let options: _WKFindOptions = self.findOptions.union(.backwards)
webView?._find(self.findString, options: options, maxCount: self.maxCount)
webView?._find(self.findString, options: options, maxCount: UInt(self.maxCount))
}
func _webView(_ webView: WKWebView!, didFailToFind string: String!) {
// ??
}
func _webView(_ webView: WKWebView!, didCountMatches matches: UInt, for string: String!) {
// TODO: Update a label
}
func _webView(_ webView: WKWebView!, didFindMatches matches: UInt, for string: String!, withMatch matchIndex: Int) {
internal func _webView(_ webView: WKWebView!, didFindMatches matches: UInt, for string: String!, withMatch matchIndex: Int) {
findOnPageView.nextResultButton.isEnabled = matches > 0
findOnPageView.prevResultButton.isEnabled = matches > 0
}

12
App/Hacks/Hacks.h Normal file
View File

@@ -0,0 +1,12 @@
//
// Hacks.h
// App
//
// Created by James Magahern on 5/5/25.
//
#import <Foundation/Foundation.h>
extern Class DecodedClass(const char *encodedClassName);
extern SEL DecodedSelector(const char *encodedSelectorName);
extern void SwizzleClassMethod(Class targetClass, SEL originalSelector, IMP replacementIMP);

31
App/Hacks/Hacks.m Normal file
View File

@@ -0,0 +1,31 @@
//
// Hacks.m
// App
//
// Created by James Magahern on 5/5/25.
//
#import "Hacks.h"
#import <objc/runtime.h>
Class DecodedClass(const char *encodedClassName) {
NSData *data = [NSData dataWithBytesNoCopy:(void *)encodedClassName length:strlen(encodedClassName) freeWhenDone:NO];
data = [[NSData alloc] initWithBase64EncodedData:data options:0];
NSString *str = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
return NSClassFromString(str);
}
SEL DecodedSelector(const char *encodedSelectorName) {
NSData *data = [NSData dataWithBytesNoCopy:(void *)encodedSelectorName length:strlen(encodedSelectorName) freeWhenDone:NO];
data = [[NSData alloc] initWithBase64EncodedData:data options:0];
NSString *str = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
return NSSelectorFromString(str);
}
void SwizzleClassMethod(Class targetClass, SEL originalSelector, IMP replacementIMP)
{
Method originalMethod = class_getClassMethod(targetClass, originalSelector);
method_setImplementation(originalMethod, replacementIMP);
}

View File

@@ -7,27 +7,43 @@
#import <CoreFoundation/CoreFoundation.h>
#import <MessageUI/MessageUI.h>
#import <WebKit/WKWebView.h>
#import <objc/runtime.h>
@interface MFMailComposeViewController (InternalMethods)
+ (BOOL)canSendMailSourceAccountManagement:(NSInteger)sourceAccountManagement;
@end
static void swizzleClassMethod(Class targetClass, SEL originalSelector, IMP replacementIMP)
{
Method originalMethod = class_getClassMethod(targetClass, originalSelector);
method_setImplementation(originalMethod, replacementIMP);
}
#import "Hacks.h"
__attribute__((constructor))
static void swizzleMFMailComposeViewController()
static void swizzleMFMailComposeViewController(void)
{
// Hacks to work around the fact that MFMailComposeViewController is broken in iOS 14+
swizzleClassMethod(MFMailComposeViewController.class, @selector(canSendMail), imp_implementationWithBlock(^BOOL(void) {
SwizzleClassMethod(MFMailComposeViewController.class, @selector(canSendMail), imp_implementationWithBlock(^BOOL(void) {
return YES;
}));
swizzleClassMethod(MFMailComposeViewController.class, @selector(canSendMailSourceAccountManagement:), imp_implementationWithBlock(^BOOL(NSInteger sam) {
SEL canSendMailSourceAccountManagement = DecodedSelector("Y2FuU2VuZE1haWxTb3VyY2VBY2NvdW50TWFuYWdlbWVudDo=");
SwizzleClassMethod(MFMailComposeViewController.class, canSendMailSourceAccountManagement, imp_implementationWithBlock(^BOOL(NSInteger sam) {
return YES;
}));
}
@interface WKWebView (Hacks)
+ (BOOL)orig_handlesURLScheme:(NSString *)scheme;
@end
@implementation WKWebView (Hacks)
+ (BOOL)orig_handlesURLScheme:(NSString *)scheme
{
if ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]) {
return NO;
}
return [self orig_handlesURLScheme:scheme];
}
@end
__attribute__((constructor))
static void swizzleWebKitConfiguration(void)
{
Method origMethod = class_getClassMethod(WKWebView.class, @selector(handlesURLScheme:));
Method replMethod = class_getClassMethod(WKWebView.class, @selector(orig_handlesURLScheme:));
method_exchangeImplementations(origMethod, replMethod);
}

View File

@@ -0,0 +1,20 @@
//
// HistoryBrowserViewController.swift
// App
//
// Created by James Magahern on 1/20/23.
//
import SwiftUI
import UIKit
@MainActor
class HistoryBrowserViewController: UIHostingController<HistoryView> {
public init(onSelectItem: @escaping (URL) -> Void) {
super.init(rootView: HistoryView(viewModel: BrowserHistory.shared.viewModel(limit: 500), onSelectItem: onSelectItem))
}
required dynamic init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

View File

@@ -0,0 +1,78 @@
//
// HistoryView.swift
// App
//
// Created by James Magahern on 1/20/23.
//
import SwiftUI
import UniformTypeIdentifiers
struct HistoryView: View {
@StateObject public var viewModel: BrowserHistory.ViewModel
@State public var selectedItems = Set<HistoryItem.ID>()
public var onSelectItem: (URL) -> Void
private let dateFormatter = DateFormatter() .. {
$0.locale = Locale.current
$0.dateStyle = .medium
$0.timeStyle = .short
}
@Environment(\.dismiss) private var dismissAction
@Environment(\.horizontalSizeClass) private var horizontalSizeClass
var body: some View {
Table(viewModel.historyItems, selection: $selectedItems) {
TableColumn("Title") { item in
VStack(alignment: .leading) {
Text(item.title.count > 0 ? item.title : item.url.absoluteString)
.lineLimit(1)
if horizontalSizeClass == .compact {
Text(item.url.shortString()).font(.caption).lineLimit(1)
Text(dateFormatter.string(from: item.lastVisited))
.font(.caption)
.foregroundColor(.secondary)
}
}
}
TableColumn("URL", value: \.url.absoluteString)
TableColumn("Last Visited") { item in
Text(dateFormatter.string(from: item.lastVisited))
}
}
.contextMenu(forSelectionType: HistoryItem.ID.self, menu: { items in
let historyItems = items.compactMap { viewModel.item(forIdentifier: $0) }
Button("Copy") {
UIPasteboard.general.setItems(historyItems.map { [
UTType.url.identifier : $0.url,
UTType.utf8PlainText.identifier : $0.url.absoluteString,
] })
}
Button("Delete") {
viewModel.deleteItems(items)
}
}, primaryAction: { items in
items.compactMap({ viewModel.item(forIdentifier: $0) }).forEach { item in
onSelectItem(item.url)
}
})
.searchable(text: $viewModel.searchQuery)
}
}
struct HistoryViewPreviewProvider: PreviewProvider {
static var previews: some View {
HistoryView(viewModel: BrowserHistory.shared.viewModel(), onSelectItem: { _ in })
.previewLayout(.fixed(width: 480.0, height: 800.0))
}
}
extension URL {
public func shortString() -> String {
return String(absoluteString.trimmingPrefix(try! Regex("(.+)://")))
}
}

View File

@@ -50,6 +50,28 @@ protocol ShortcutResponder: AnyObject {
@objc
optional func openInReaderMode(_ sender: Any?)
@objc
optional func showHistory(_ sender: Any?)
@objc
optional func handleOpenURL(_ sender: Any?, forEvent event: OpenURLEvent?)
@objc
optional func lowerScriptPolicyRestriction(_ sender: Any?)
@objc
optional func raiseScriptPolicyRestriction(_ sender: Any?)
@objc
optional func zoomToActualSize(_ sender: Any?)
}
public class OpenURLEvent: UIEvent {
let url: URL
public init(url: URL) {
self.url = url
}
}
fileprivate extension Array {
@@ -140,6 +162,22 @@ public class KeyboardShortcuts {
action: #selector(ShortcutResponder.stop)
)
]),
UIMenu(options: .displayInline, children: [
// Raise Script Policy Restriction
UIKeyCommand(
modifiers: [.alternate], input: "x",
title: "Raise Script Policy Restriction",
action: #selector(ShortcutResponder.raiseScriptPolicyRestriction)
),
// Lower Script Policy Restriction
UIKeyCommand(
modifiers: [.alternate], input: "c",
title: "Lower Script Policy Restriction",
action: #selector(ShortcutResponder.lowerScriptPolicyRestriction)
),
])
].removeNulls()
case .go:
@@ -188,6 +226,30 @@ public class KeyboardShortcuts {
case .view:
return [
// Zoom
UIMenu(options: .displayInline, children: [
// Actual Size
UIKeyCommand(
modifiers: .command, input: "0",
title: "Actual Size",
action: #selector(ShortcutResponder.zoomToActualSize)
),
// Increase Zoom
UIKeyCommand(
modifiers: .command, input: "=",
title: "Zoom In",
action: #selector(UIResponder.increaseSize)
),
// Go Forward
UIKeyCommand(
modifiers: .command, input: "-",
title: "Zoom Out",
action: #selector(UIResponder.decreaseSize)
),
]),
// Toggle Dark Mode
UIKeyCommand(
modifiers: [.command], input: "M",

View File

@@ -8,7 +8,6 @@ html, iframe {
-webkit-filter: invert(100%) !important;
}
em,
img,
svg,
form,

View File

@@ -30,7 +30,7 @@ class BrowserSceneDelegate: UIResponder, UIWindowSceneDelegate {
if let urlContext = connectionOptions.urlContexts.first {
let url = urlContext.url
browserViewController.tab.beginLoadingURL(url)
browserViewController.currentTab.beginLoadingURL(url)
}
#if targetEnvironment(macCatalyst)
@@ -59,8 +59,8 @@ class BrowserSceneDelegate: UIResponder, UIWindowSceneDelegate {
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>)
{
for urlContext in URLContexts {
if browserViewController?.tab.url == nil {
browserViewController?.tab.beginLoadingURL(urlContext.url)
if browserViewController?.currentTab.url == nil {
browserViewController?.currentTab.beginLoadingURL(urlContext.url)
} else {
browserViewController?.createNewTab(withURL: urlContext.url)
}

View File

@@ -32,18 +32,45 @@ struct TextFieldContentConfiguration : UIContentConfiguration
{
var text: String = ""
var placeholderText: String? = nil
var textChanged: ((String) -> Void)
var textChanged: ((String) -> Void)? = nil
var pressedReturn: ((UITextField) -> Void)? = nil
var keyboardType: UIKeyboardType = .default
var returnKeyType: UIReturnKeyType = .default
func makeContentView() -> UIView & UIContentView {
let textField = UITextField(frame: .zero)
textField.borderStyle = .roundedRect
textField.autocorrectionType = .no
textField.autocapitalizationType = .none
textField.keyboardType = keyboardType
textField.returnKeyType = returnKeyType
return GenericContentView<UITextField, TextFieldContentConfiguration>(configuration: self, view: textField) { config, textField in
textField.text = config.text
textField.placeholder = config.placeholderText
textField.addAction(UIAction { _ in config.textChanged(textField.text ?? "") }, for: .editingChanged)
if let textChanged = config.textChanged {
textField.addAction(UIAction { _ in textChanged(textField.text ?? "") }, for: .editingChanged)
}
if let pressedReturn = config.pressedReturn {
class ReturnDelegate : NSObject, UITextFieldDelegate {
var pressedReturn: ((UITextField) -> Void)
public init(pressedReturn: @escaping ((UITextField) -> Void)) {
self.pressedReturn = pressedReturn
}
public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
pressedReturn(textField)
return false
}
}
let delegate = ReturnDelegate(pressedReturn: pressedReturn)
objc_setAssociatedObject(textField, "returnDelegate", delegate, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
textField.delegate = delegate
}
}
}
@@ -111,7 +138,7 @@ class GeneralSettingsViewController: UIViewController
layoutSize: headerFooterSize,
elementKind: UICollectionView.elementKindSectionHeader,
alignment: .topLeading,
absoluteOffset: CGPoint(x: insets.leading, y: insets.top)
absoluteOffset: CGPoint(x: insets.leading, y: insets.top + 5.0)
)
sectionHeader.extendsBoundary = false
sectionHeader.contentInsets = insets
@@ -173,7 +200,10 @@ class GeneralSettingsViewController: UIViewController
placeholderText: "https://sync.server.com",
textChanged: { newString in
Settings.shared.syncServer = newString
}
},
pressedReturn: { $0.resignFirstResponder() },
keyboardType: .URL,
returnKeyType: .done
)
}
@@ -203,6 +233,7 @@ class GeneralSettingsViewController: UIViewController
super.init(nibName: nil, bundle: nil)
collectionView.delegate = self
tabBarItem.title = "General"
tabBarItem.image = UIImage(systemName: "gear")
}
@@ -228,3 +259,9 @@ class GeneralSettingsViewController: UIViewController
}
}
extension GeneralSettingsViewController : UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
false
}
}

View File

@@ -229,13 +229,19 @@ class CreateRedirectRuleViewController: UICollectionViewController
sectionHeaderImageView.contentMode = .scaleAspectFit
fromHostField.placeholder = "https://fromhostname.com"
fromHostField.placeholder = "fromhostname.com"
fromHostField.autocorrectionType = .no
fromHostField.autocapitalizationType = .none
fromHostField.keyboardType = .URL
fromHostField.returnKeyType = .next
fromHostField.delegate = self
toHostField.placeholder = "https://tohostname.com"
toHostField.placeholder = "tohostname.com"
toHostField.autocorrectionType = .no
toHostField.autocapitalizationType = .none
toHostField.keyboardType = .URL
toHostField.returnKeyType = .done
toHostField.delegate = self
}
required init?(coder: NSCoder) {
@@ -256,3 +262,15 @@ class CreateRedirectRuleViewController: UICollectionViewController
}
}
extension CreateRedirectRuleViewController : UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if textField == fromHostField {
toHostField.becomeFirstResponder()
} else if textField == toHostField {
toHostField.resignFirstResponder()
}
return false
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View File

@@ -1,110 +1,114 @@
{
"images" : [
{
"filename" : "icon-Notification@2x.png",
"idiom" : "iphone",
"filename" : "AppIcon-20.0x20.0@2x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "icon-Notification@3x.png",
"idiom" : "iphone",
"filename" : "AppIcon-20.0x20.0@3x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "20x20"
},
{
"filename" : "icon-Settings@2x.png",
"idiom" : "iphone",
"filename" : "AppIcon-29.0x29.0@2x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "icon-Settings@3x.png",
"idiom" : "iphone",
"filename" : "AppIcon-29.0x29.0@3x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "29x29"
},
{
"filename" : "icon-Spotlight-40@2x.png",
"idiom" : "iphone",
"filename" : "AppIcon-38.0x38.0@2x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "38x38"
},
{
"filename" : "AppIcon-38.0x38.0@3x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "38x38"
},
{
"filename" : "AppIcon-40.0x40.0@2x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "icon-Spotlight-40@3x.png",
"idiom" : "iphone",
"filename" : "AppIcon-40.0x40.0@3x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "40x40"
},
{
"filename" : "icon-60@2x.png",
"idiom" : "iphone",
"filename" : "AppIcon-60.0x60.0@2x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "60x60"
},
{
"filename" : "icon-60@3x.png",
"idiom" : "iphone",
"filename" : "AppIcon-60.0x60.0@3x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "60x60"
},
{
"filename" : "icon-Notification~ipad.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"filename" : "icon-Notification@2x ~ipad.png",
"idiom" : "ipad",
"filename" : "AppIcon-64.0x64.0@2x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "20x20"
"size" : "64x64"
},
{
"filename" : "icon-Settings~ipad.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
"filename" : "AppIcon-64.0x64.0@3x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "3x",
"size" : "64x64"
},
{
"filename" : "icon-Settings@2x~ipad.png",
"idiom" : "ipad",
"filename" : "AppIcon-68.0x68.0@2x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "29x29"
"size" : "68x68"
},
{
"filename" : "icon-Spotlight-40~ipad.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"filename" : "icon-Spotlight-40@2x~ipad.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "icon-76~ipad.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"filename" : "icon-76@2x~ipad.png",
"idiom" : "ipad",
"filename" : "AppIcon-76.0x76.0@2x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "76x76"
},
{
"filename" : "icon-83.5@2x~ipad.png",
"idiom" : "ipad",
"filename" : "AppIcon-83.5x83.5@2x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"filename" : "iconios~marketing-1.png",
"idiom" : "ios-marketing",
"filename" : "AppIcon-1024.0x1024.0@1x.png",
"idiom" : "universal",
"platform" : "ios",
"scale" : "1x",
"size" : "1024x1024"
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 762 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 336 KiB

View File

@@ -34,6 +34,8 @@
</array>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>

View File

@@ -5,8 +5,9 @@
#import "SBRProcessBundleBridge.h"
#import "SBRScriptPolicy.h"
#import "WebKitDefines.h"
// SPI
#import <UIKit/UITextField_Private.h>
#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/_WKFindDelegate.h>

View File

@@ -6,9 +6,5 @@
<true/>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.developer.web-browser</key>
<true/>
<key>com.apple.developer.device-information.user-assigned-device-name</key>
<true/>
</dict>
</plist>

View File

@@ -0,0 +1,19 @@
//
// WebKitDefines.h
// SBrowser
//
// Created by James Magahern on 4/11/25.
//
#ifndef WebKitDefines_h
#define WebKitDefines_h
#define WK_API_AVAILABLE(...)
#define WK_API_UNAVAILABLE(...)
#define WK_CLASS_AVAILABLE(...) __attribute__((visibility("default"))) WK_API_AVAILABLE(__VA_ARGS__)
#define WK_API_DEPRECATED(_message, ...) __attribute__((deprecated(_message)))
#define WK_API_DEPRECATED_WITH_REPLACEMENT(_replacement, ...) __attribute__((deprecated("use " #_replacement)))
#define WK_CLASS_DEPRECATED_WITH_REPLACEMENT(_replacement, ...) __attribute__((visibility("default"))) __attribute__((deprecated("use " #_replacement)))
#endif /* WebKitDefines_h */

View File

@@ -19,12 +19,8 @@ class Tab: NSObject, SBRProcessBundleBridgeDelegate
public var tabInfo: TabInfo {
get {
TabInfo(
title: loadedWebView?.title,
urlString: loadedWebView?.url?.absoluteString ?? self.homeURL?.absoluteString,
faviconData: self.favicon?.pngData(),
identifier: self.identifier
)
updateMetadata()
return _tabInfo
}
}
@@ -43,6 +39,8 @@ class Tab: NSObject, SBRProcessBundleBridgeDelegate
}
public var policyManager: ResourcePolicyManager
private var _tabInfo: TabInfo = TabInfo()
private var loadedWebView: WKWebView? = nil
public var title: String? { get { tabInfo.title } }
public var url: URL? {
@@ -82,6 +80,7 @@ class Tab: NSObject, SBRProcessBundleBridgeDelegate
@Published public var favicon: UIImage?
public var loadError: Error?
public var contentProcessTerminated: Bool = false
private var faviconHost: String?
private var faviconRequest: AnyCancellable?
@@ -151,4 +150,15 @@ class Tab: NSObject, SBRProcessBundleBridgeDelegate
.assign(to: \.favicon, on: self)
}
}
private func updateMetadata() {
guard contentProcessTerminated == false else { return }
_tabInfo = TabInfo(
title: loadedWebView?.title,
urlString: loadedWebView?.url?.absoluteString ?? self.homeURL?.absoluteString,
faviconData: self.favicon?.pngData(),
identifier: self.identifier
)
}
}

View File

@@ -33,6 +33,10 @@ class TabController
tabs.first { $0.identifier == identifier }
}
func tab(forWebView webView: WKWebView) -> Tab? {
tabs.first { $0.webView == webView }
}
func createNewTab(url: URL?) -> Tab {
return self.createNewTab(url: url, webViewConfiguration: nil)
}

View File

@@ -6,7 +6,6 @@
//
import UIKit
import QuartzCore_Private
class SecurityIndicatorView: UIView
{
@@ -62,10 +61,6 @@ class TitlebarView: UIView
private let separatorView = UIView(frame: .zero)
private let securityIndicatorView = SecurityIndicatorView()
override var _sceneDraggingBehaviorOnPan: _UIViewSceneDraggingBehaviorOnPan {
_UIViewSceneDraggingBehaviorOnPan.dragScene
}
convenience init() {
self.init(frame: .zero)
addSubview(backgroundView)
@@ -74,7 +69,7 @@ class TitlebarView: UIView
addSubview(separatorView)
separatorView.backgroundColor = UIColor(white: 1.0, alpha: 0.20)
separatorView.layer.compositingFilter = kCAFilterPlusL
separatorView.layer.compositingFilter = "kCAFilterPlusL"
titleLabelView.textColor = .white
titleLabelView.layer.shadowColor = UIColor.black.cgColor
@@ -88,6 +83,11 @@ class TitlebarView: UIView
securityIndicatorView.label.font = UIFont.systemFont(ofSize: 10.0)
backgroundView.alpha = 0.98
// Make draggable
if #available(iOS 17.0, *) {
addInteraction(UIWindowSceneDragInteraction())
}
}
func setTitle(_ title: String) {

View File

@@ -9,9 +9,18 @@ import UIKit
class ToolbarView: UIView
{
var urlBar: URLBar? { didSet { containerView.addSubview(urlBar!) } }
var urlBar: URLBar? {
didSet {
guard let urlBar else { return }
containerView.addSubview(urlBar)
var cancelButtonVisible: Bool = false { didSet { layoutSubviews() } }
urlBar.textField.addAction(.init(handler: { [unowned self] _ in
layoutLatch.activate()
}), for: [ .editingDidBegin, .editingDidEnd ])
}
}
var cancelButtonVisible: Bool = false { didSet { setNeedsLayout() } }
let containerView = UIView(frame: .zero)
let backgroundView = GradientView(direction: .vertical, colors: [
@@ -23,6 +32,9 @@ class ToolbarView: UIView
let leadingButtonsView = ToolbarButtonContainerView(frame: .zero)
let trailingButtonsView = ToolbarButtonContainerView(frame: .zero)
// Something I'm sure I'll regret: to ensure animation with the keyboard, latch layout until we get the right signal.
lazy var layoutLatch = LayoutLatch(self)
convenience init()
{
self.init(frame: .zero)
@@ -54,6 +66,7 @@ class ToolbarView: UIView
override func layoutSubviews()
{
guard !layoutLatch.latched else { return }
super.layoutSubviews()
let shadowPath = UIBezierPath(rect: bounds)

View File

@@ -66,10 +66,13 @@ class ToolbarViewController: UIViewController
newTabButton.setImage(UIImage(systemName: "plus"), for: .normal)
let toolbarAnimationDuration: TimeInterval = 0.3
urlBar.textField.addAction(.init(handler: { [traitCollection, toolbarView, urlBar] _ in
if traitCollection.horizontalSizeClass == .compact {
UIView.animate(withDuration: toolbarAnimationDuration) {
toolbarView.cancelButtonVisible = urlBar.textField.isFirstResponder
urlBar.textField.addAction(.init(handler: { [weak self] _ in
guard let self, let parent else { return }
// xxx: Not sure why I need to refer to parent here. This view controller isn't inheriting anything.
if parent.traitCollection.horizontalSizeClass == .compact {
UIView.animate(withDuration: toolbarAnimationDuration) { [unowned self] in
self.toolbarView.cancelButtonVisible = self.urlBar.textField.isFirstResponder
}
}
}), for: [ .editingDidBegin, .editingDidEnd ])
@@ -78,12 +81,10 @@ class ToolbarViewController: UIViewController
urlBar.textField.resignFirstResponder()
}), for: .touchUpInside)
traitCollectionDidChange(nil)
reconfigureButtons(for: traitCollection.horizontalSizeClass)
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
public func reconfigureButtons(for horizontalSizeClass: UIUserInterfaceSizeClass) {
toolbarView.leadingButtonsView.removeAllButtonViews()
toolbarView.trailingButtonsView.removeAllButtonViews()
@@ -92,7 +93,7 @@ class ToolbarViewController: UIViewController
}
// Setup toolbar based on trait collection
if traitCollection.horizontalSizeClass == .compact {
if horizontalSizeClass == .compact {
toolbarView.trailingButtonsView.addButtonView(scriptControllerIconView)
toolbarView.trailingButtonsView.addButtonView(newTabButton)
toolbarView.trailingButtonsView.addButtonView(windowButton)

View File

@@ -153,20 +153,12 @@ class URLBar: ReliefButton
textField.font = .systemFont(ofSize: 13.0)
textField.clearButtonMode = .never
textField.placeholder = "URL or search term"
textField.addAction(UIAction(handler: { [unowned self] _ in
// Mask view visibility is affected by editing state.
self.layoutSubviews()
}), for: [ .editingDidBegin, .editingDidEnd ])
textField.keyCommands = [
UIKeyCommand(action: #selector(Self.downKeyPressed), input: UIKeyCommand.inputDownArrow)
.prioritizeOverSystem()
]
addSubview(textField)
textField.addAction(.init(handler: { [textField, refreshButton ] _ in
refreshButton.isHidden = textField.isFirstResponder
}), for: [ .editingDidBegin, .editingDidEnd ])
refreshButton.tintColor = .secondaryLabel
refreshButton.setImage(refreshImage, for: .normal)
refreshButton.isPointerInteractionEnabled = true
@@ -189,8 +181,9 @@ class URLBar: ReliefButton
documentSeparatorView.backgroundColor = .secondarySystemFill
addSubview(documentSeparatorView)
controlsView.autoresizingMask = []
controlsView.clearButton.addAction(.init(handler: { [textField] _ in
textField.clearText()
textField.text = ""
}), for: .primaryActionTriggered)
controlsView.autocorrectButton.addAction(.init(handler: { [unowned self] _ in
@@ -281,8 +274,9 @@ class URLBar: ReliefButton
}
private func fadeBackgroundImageForSize(_ size: CGSize, cutoffLocation: CGFloat) -> UIImage? {
var image: UIImage? = nil
guard size.width > .leastNonzeroMagnitude && size.height > .leastNonzeroMagnitude else { return nil }
var image: UIImage? = nil
UIGraphicsBeginImageContext(CGSize(width: size.width, height: 1.0))
if let context = UIGraphicsGetCurrentContext() {
let gradientColorsArray = [
@@ -292,6 +286,7 @@ class URLBar: ReliefButton
UIColor(white: 1.0, alpha: 0.08).cgColor
]
let cutoffLocation = CGFloat.minimum(0.9, cutoffLocation)
let locations: [CGFloat] = [
0.0, cutoffLocation, cutoffLocation + 0.10, 1.0
]
@@ -343,6 +338,9 @@ class URLBar: ReliefButton
)
documentSeparatorView.frame = documentSeparatorView.frame.insetBy(dx: 0.0, dy: 3.0)
// Text field controls
controlsView.frame = CGRect(origin: controlsView.frame.origin, size: controlsView.sizeThatFits(bounds.size))
// Text field
let textFieldPadding: CGFloat = 6.0
let textFieldOrigin = CGPoint(x: documentButton.frame.maxX + textFieldPadding, y: 0.0)
@@ -360,8 +358,18 @@ class URLBar: ReliefButton
let refreshButtonSize = CGSize(width: textField.frame.height, height: textField.frame.height)
refreshButton.frame = CGRect(origin: CGPoint(x: bounds.width - refreshButtonSize.width, y: 0), size: refreshButtonSize)
// Refresh vs. controls view visibility
let isFocused = textField.isFirstResponder
if isFocused {
controlsView.alpha = 1.0
refreshButton.alpha = 0.0
} else {
controlsView.alpha = 0.0
refreshButton.alpha = 1.0
}
// Error button
if case .error(error: _) = loadProgress, !textField.isFirstResponder {
if case .error(error: _) = loadProgress, !isFocused {
errorButton.isHidden = false
errorButton.sizeToFit()
errorButton.frame = CGRect(
@@ -379,7 +387,7 @@ class URLBar: ReliefButton
// Fade mask
fadeMaskView.frame = textField.bounds
fadeMaskView.image = fadeBackgroundImageForSize(fadeMaskView.frame.size, cutoffLocation: fadeCutoffLocation)
if !textField.isFirstResponder {
if !isFocused {
textField.mask = fadeMaskView
} else {
textField.mask = nil

View File

@@ -33,14 +33,14 @@ extension CGRect
public func centeredY(inRect: CGRect) -> CGRect {
var rect = self
rect.origin.y = CGRound(inRect.origin.y + (inRect.height - rect.height) / 2.0)
rect.origin.y = (inRect.origin.y + (inRect.height - rect.height) / 2.0).rounded()
return rect
}
public func centeredX(inRect: CGRect) -> CGRect {
var rect = self
rect.origin.x = CGRound(inRect.origin.x + (inRect.width - rect.width) / 2.0)
rect.origin.x = (inRect.origin.x + (inRect.width - rect.width) / 2.0).rounded()
return rect
}

View File

@@ -0,0 +1,30 @@
//
// LayoutLatch.swift
// App
//
// Created by James Magahern on 8/10/23.
//
import Foundation
class LayoutLatch {
public weak var view: UIView?
public private(set) var latched: Bool = false
init(_ view: UIView) {
self.view = view
}
public func activate() {
latched = true
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(100)) { [weak self] in
self?.deactivate()
}
}
public func deactivate() {
latched = false
view?.setNeedsLayout()
}
}

View File

@@ -0,0 +1,33 @@
//
// StringUtilities.swift
// App
//
// Created by James Magahern on 7/31/24.
//
import Foundation
extension String {
internal func middleTruncatedString(maximumLength: Int) -> String {
if maximumLength > self.count {
return self
}
// Compute replacement range
let pivot = self.count / 2
let truncationLength = self.count - maximumLength
let pivotIndex = self.index(startIndex, offsetBy: pivot)
let startIndex = self.index(pivotIndex, offsetBy: -truncationLength / 2)
let endIndex = self.index(pivotIndex, offsetBy: truncationLength / 2)
return replacingCharacters(in: startIndex..<endIndex, with: "")
}
}
extension URL {
internal var securityOrigin: String {
// TODO: This could be smarter
return self.host() ?? ""
}
}

View File

@@ -7,6 +7,15 @@
import UIKit
infix operator .. : AssignmentPrecedence
@discardableResult @inline(__always) @inlinable
public func .. <T: Any>(it: T, apply: (inout T) throws -> Void) rethrows -> T {
var it = it
try apply(&it)
return it
}
protocol Conf { }
extension Conf {

View File

@@ -36,8 +36,6 @@ NS_SWIFT_NAME(ProcessBundleBridge)
@property (nonatomic, assign) BOOL allowAllScripts; // default is NO
@property (nonatomic, assign) BOOL darkModeEnabled;
@property (nonatomic, readonly) BOOL webContentProcessConnected;
- (instancetype)initWithWebViewConfiguration:(nullable WKWebViewConfiguration *)webViewConfiguration NS_DESIGNATED_INITIALIZER;
- (void)policyDataSourceDidChange;

View File

@@ -7,64 +7,117 @@
#import "SBRProcessBundleBridge.h"
#import "SBRWebProcessDelegate.h"
#import "SBRWebProcessProxy.h"
#import "SBRScriptPolicy.h"
#import "Hacks.h"
#import <OSLog/OSLog.h>
#import <WebKit/_WKRemoteObjectInterface.h>
#import <WebKit/_WKRemoteObjectRegistry.h>
#import <WebKit/_WKProcessPoolConfiguration.h>
#import <WebKit/_WKUserStyleSheet.h>
#import <WebKit/WKProcessPoolPrivate.h>
#import <WebKit/WKWebViewPrivate.h>
#import <WebKit/WKWebViewConfigurationPrivate.h>
#import <WebKit/WKUserContentControllerPrivate.h>
@interface SBRProcessBundleBridge () <SBRWebProcessDelegate>
#define WKUserStyleSheet id
#define WKUserStyleSheetEncodedClassName "X1dLVXNlclN0eWxlU2hlZXQ="
@interface StyleSheet : NSObject <NSCopying>
@property (nonatomic, readonly, copy) NSString *source;
@property (nonatomic, readonly, copy) NSURL *baseURL;
@property (nonatomic, readonly, getter=isForMainFrameOnly) BOOL forMainFrameOnly;
- (instancetype)initWithSource:(NSString *)source forMainFrameOnly:(BOOL)forMainFrameOnly;
@end
@interface WKUserContentController (Private)
- (void)__addUserStyleSheet:(WKUserStyleSheet)userStyleSheet;
- (void)__removeUserStyleSheet:(WKUserStyleSheet)userStyleSheet;
- (void)__addUserScriptImmediately:(WKUserScript *)userScript;
@end
@implementation WKUserContentController (Private)
- (void)__addUserStyleSheet:(id)userStyleSheet
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:DecodedSelector("X2FkZFVzZXJTdHlsZVNoZWV0Og==") withObject:userStyleSheet];
#pragma clang diagnostic pop
}
- (void)__removeUserStyleSheet:(id)userStyleSheet
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:DecodedSelector("X3JlbW92ZVVzZXJTdHlsZVNoZWV0Og==") withObject:userStyleSheet];
#pragma clang diagnostic pop
}
- (void)__addUserScriptImmediately:(WKUserScript *)userScript
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self performSelector:DecodedSelector("X2FkZFVzZXJTY3JpcHRJbW1lZGlhdGVseTo=") withObject:userScript];
#pragma clang diagnostic pop
}
@end
#define LOG_DEBUG(format, ...) os_log_debug(_log, format, ##__VA_ARGS__)
#define LOG_ERROR(format, ...) os_log_error(_log, format, ##__VA_ARGS__)
@interface NSURLResponse (BridgeAdditions)
@property (nonatomic, readonly) BOOL isJavascriptResponse;
@end
@implementation NSURLResponse (BridgeAdditions)
- (BOOL)isJavascriptResponse
{
NSString *extension = [[self URL] pathExtension];
if ([[extension lowercaseString] isEqualToString:@"js"]) {
return YES;
}
NSString *MIMEType = [self MIMEType];
if ([[MIMEType lowercaseString] containsString:@"javascript"]) {
return YES;
}
return NO;
}
@end
@interface SBRProcessBundleBridge () <WKURLSchemeHandler>
@end
@implementation SBRProcessBundleBridge {
os_log_t _log;
WKWebView *_webView;
WKWebViewConfiguration *_webViewConfiguration;
WKProcessPool *_processPool;
id<SBRWebProcessProxy> _webProcessProxy;
_WKUserStyleSheet *_darkModeStyleSheet;
WKUserStyleSheet _darkModeStyleSheet;
WKUserScript *_readabilityScript;
NSArray<WKUserScript *> *_userScripts;
dispatch_queue_t _dataTasksAccessQueue;
NSMutableDictionary<NSURLRequest *, NSURLSessionDataTask *> *_dataTasks;
// These come from settings.
_WKUserStyleSheet *_customizedUserStylesheet;
WKUserStyleSheet _customizedUserStylesheet;
WKUserScript *_customizedUserScript;
}
- (void)tearDown
{
[[_webView _remoteObjectRegistry] unregisterExportedObject:self interface:[self _webProcessDelegateInterface]];
}
- (_WKRemoteObjectInterface *)_webProcessDelegateInterface
{
static dispatch_once_t onceToken;
static _WKRemoteObjectInterface *interface = nil;
dispatch_once(&onceToken, ^{
interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(SBRWebProcessDelegate)];
});
return interface;
}
- (_WKRemoteObjectInterface *)_webProcessProxyInterface
{
static dispatch_once_t onceToken;
static _WKRemoteObjectInterface *interface = nil;
dispatch_once(&onceToken, ^{
interface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(SBRWebProcessProxy)];
});
return interface;
// This was used to unregister the delegate with the web process.
}
- (instancetype)initWithWebViewConfiguration:(WKWebViewConfiguration *)webViewConfiguration
@@ -72,32 +125,22 @@
self = [super init];
if (self) {
if (!webViewConfiguration) {
_log = os_log_create("net.buzzert.attractor.webview", "bridge");
webViewConfiguration = [[WKWebViewConfiguration alloc] init];
// Inject bundle
_WKProcessPoolConfiguration *poolConfiguration = [[_WKProcessPoolConfiguration alloc] init];
NSURL *bundleURL = [[[NSBundle mainBundle] builtInPlugInsURL] URLByAppendingPathComponent:@"SBrowserProcessBundle.bundle"];
// Make sure it exists. Bail if otherwise.
NSBundle *pluginBundle = [NSBundle bundleWithURL:bundleURL];
NSAssert(pluginBundle != nil, @"Attix process bundle not found at %@", bundleURL.path);
[poolConfiguration setInjectedBundleURL:bundleURL];
// Set up process pool
_processPool = [[WKProcessPool alloc] _initWithConfiguration:poolConfiguration];
// Initialize allowed origins now
NSDictionary<NSString *, NSNumber *> *policies = [_policyDataSource scriptPolicyTypeByOrigin];
NSArray<NSString *> *allowedOrigins = [[_policyDataSource allowedOriginsForScriptResources] allObjects];
[_processPool _setObject:allowedOrigins forBundleParameter:SBRGetAllowedOriginsKey()];
[_processPool _setObject:@(_allowAllScripts) forBundleParameter:SBRGetAllScriptsAllowedKey()];
[_processPool _setObject:policies forBundleParameter:SBRGetPolicyTypeByOriginKey()];
_processPool = [[WKProcessPool alloc] init];
webViewConfiguration.processPool = _processPool;
webViewConfiguration._waitsForPaintAfterViewDidMoveToWindow = NO;
webViewConfiguration._applePayEnabled = YES;
_dataTasks = [NSMutableDictionary dictionary];
_dataTasksAccessQueue = dispatch_queue_create("net.buzzert.attractor.dataTasksAccess", DISPATCH_QUEUE_SERIAL);
[webViewConfiguration setURLSchemeHandler:self forURLScheme:@"http"];
[webViewConfiguration setURLSchemeHandler:self forURLScheme:@"https"];
}
_webViewConfiguration = webViewConfiguration;
@@ -113,16 +156,10 @@
// Instantiate web view
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:webViewConfiguration];
if ([webView respondsToSelector:@selector(_setFindInteractionEnabled:)]) {
webView._findInteractionEnabled = YES;
if (@available(iOS 16.0, *)) {
webView.findInteractionEnabled = YES;
}
// Configure proxy interface (interface to remote web process)
_webProcessProxy = [[webView _remoteObjectRegistry] remoteObjectProxyWithInterface:[self _webProcessProxyInterface]];
// Configure delegate interface (registering us as the web process delegate for the remote process)
[[webView _remoteObjectRegistry] registerExportedObject:self interface:[self _webProcessDelegateInterface]];
_webView = webView;
}
@@ -151,9 +188,7 @@
- (void)reloadCustomizedUserScriptsAndStylesheets
{
WKUserContentController *userContentController = [_webViewConfiguration userContentController];
if (_customizedUserScript) {
[userContentController _removeUserScript:_customizedUserScript];
}
[userContentController removeAllUserScripts];
NSString *scriptSource = [[NSUserDefaults standardUserDefaults] stringForKey:@"userScript"];
if ([scriptSource length]) {
@@ -162,55 +197,123 @@
}
if (_customizedUserStylesheet) {
[userContentController _removeUserStyleSheet:_customizedUserStylesheet];
[userContentController __removeUserStyleSheet:_customizedUserStylesheet];
}
NSString *stylesheetSource = [[NSUserDefaults standardUserDefaults] stringForKey:@"userStylesheet"];
if ([stylesheetSource length]) {
_customizedUserStylesheet = [[_WKUserStyleSheet alloc] initWithSource:stylesheetSource forMainFrameOnly:YES];
[userContentController _addUserStyleSheet:_customizedUserStylesheet];
_customizedUserStylesheet = [[DecodedClass(WKUserStyleSheetEncodedClassName) alloc] initWithSource:stylesheetSource forMainFrameOnly:YES];
[userContentController __addUserStyleSheet:_customizedUserStylesheet];
}
}
#pragma mark <SBRWebProcessDelegate>
- (void)webProcessDidConnect
{
NSLog(@"SBRProcessBundleBridge: did connect. Saying hello, syncing allowlist");
_webContentProcessConnected = YES;
[_webProcessProxy hello];
[self policyDataSourceDidChange];
}
#pragma mark Former <SBRWebProcessDelegate> methods
- (void)webProcessDidAllowScriptWithOrigin:(NSString *)origin
{
dispatch_async(dispatch_get_main_queue(), ^{
[[self delegate] webProcess:self didAllowScriptResourceFromOrigin:origin];
});
}
- (void)webProcessDidBlockScriptWithOrigin:(NSString *)origin
{
dispatch_async(dispatch_get_main_queue(), ^{
[[self delegate] webProcess:self didBlockScriptResourceFromOrigin:origin];
});
}
#pragma mark <WKURLSchemeHandler>
- (void)webView:(WKWebView *)webView startURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask
{
NSString *hostOrigin = [[_webView URL] host];
NSURLRequest *request = [urlSchemeTask request];
LOG_DEBUG("Start URL scheme task: request: %@", request);
__weak __auto_type welf = self;
NSURLSessionDataTask *dataTask = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
{
if (!welf) return;
__strong __auto_type sself = welf;
if (error != nil) {
[urlSchemeTask didFailWithError:error];
} else if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSURL *requestURL = [request URL];
NSString *resourceOrigin = [requestURL host];
const __auto_type allowResource = ^{
os_log_debug(sself->_log, "Allowing resource: %@", requestURL.lastPathComponent);
[urlSchemeTask didReceiveResponse:response];
[urlSchemeTask didReceiveData:data];
[urlSchemeTask didFinish];
[self webProcessDidAllowScriptWithOrigin:resourceOrigin];
};
const __auto_type denyResource = ^{
os_log_debug(sself->_log, "Blocking resource: %@", requestURL.lastPathComponent);
NSHTTPURLResponse *altResponse = [[NSHTTPURLResponse alloc] initWithURL:requestURL
MIMEType:@"application/javascript"
expectedContentLength:0 textEncodingName:@"utf8"];
[urlSchemeTask didReceiveResponse:altResponse];
[urlSchemeTask didReceiveData:[NSData data]];
[urlSchemeTask didFinish];
[self webProcessDidBlockScriptWithOrigin:resourceOrigin];
};
// Check MIME type for JavaScript responses.
if ([response isJavascriptResponse] && ![sself allowAllScripts]) {
dispatch_async(sself->_dataTasksAccessQueue, ^{
NSDictionary<NSString *, NSNumber *> *policyTypes = [sself->_policyDataSource scriptPolicyTypeByOrigin];
NSNumber *policyType = [policyTypes objectForKey:hostOrigin];
SBRScriptPolicy *policy = [[SBRScriptPolicy alloc] initWithSecurityOrigin:hostOrigin policyType:[policyType integerValue]];
if ([policy allowsExternalJavaScriptResourceOrigin:resourceOrigin]) {
allowResource();
} else {
denyResource();
}
});
} else {
allowResource();
}
} else {
[urlSchemeTask didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:0 userInfo:nil]];
}
[sself->_dataTasks removeObjectForKey:request];
}];
[_dataTasks setObject:dataTask forKey:request];
[dataTask resume];
}
- (void)webView:(WKWebView *)webView stopURLSchemeTask:(id<WKURLSchemeTask>)urlSchemeTask
{
NSURLRequest *request = [urlSchemeTask request];
NSURLSessionDataTask *dataTask = [_dataTasks objectForKey:request];
if (dataTask) {
if ([dataTask state] != NSURLSessionTaskStateCanceling) {
[dataTask cancel];
}
[_dataTasks removeObjectForKey:request];
}
}
#pragma mark Actions
- (void)policyDataSourceDidChange
{
NSArray<NSString *> *allowedOrigins = [[_policyDataSource allowedOriginsForScriptResources] allObjects];
[_processPool _setObject:allowedOrigins forBundleParameter:SBRGetAllowedOriginsKey()];
[_webProcessProxy syncAllowedResourceOrigins:allowedOrigins];
NSDictionary<NSString *, NSNumber *> *policyTypes = [_policyDataSource scriptPolicyTypeByOrigin];
[_processPool _setObject:policyTypes forBundleParameter:SBRGetPolicyTypeByOriginKey()];
[_webProcessProxy syncPolicyTypes:policyTypes];
// This was used when we had to signal the process bundle.
}
- (void)setAllowAllScripts:(BOOL)allowAllScripts
{
_allowAllScripts = allowAllScripts;
[_processPool _setObject:@(_allowAllScripts) forBundleParameter:SBRGetAllScriptsAllowedKey()];
[_webProcessProxy setAllScriptsAllowed:allowAllScripts];
}
- (void)setDarkModeEnabled:(BOOL)darkModeEnabled
@@ -223,16 +326,15 @@
if (!_darkModeStyleSheet) {
NSURL *styleSheetURL = [[NSBundle mainBundle] URLForResource:@"darkmode" withExtension:@"css"];
NSString *styleSheetSource = [NSString stringWithContentsOfURL:styleSheetURL encoding:NSUTF8StringEncoding error:nil];
_darkModeStyleSheet = [[_WKUserStyleSheet alloc] initWithSource:styleSheetSource forMainFrameOnly:NO];
_darkModeStyleSheet = [[DecodedClass(WKUserStyleSheetEncodedClassName) alloc] initWithSource:styleSheetSource forMainFrameOnly:NO];
}
[userContentController _addUserStyleSheet:_darkModeStyleSheet];
[userContentController __addUserStyleSheet:_darkModeStyleSheet];
} else if (_darkModeStyleSheet) {
[userContentController _removeUserStyleSheet:_darkModeStyleSheet];
[userContentController __removeUserStyleSheet:_darkModeStyleSheet];
}
}
- (void)parseDocumentForReaderMode:(void (^)(NSString * _Nonnull))completionBlock
{
WKUserContentController *userContentController = [_webViewConfiguration userContentController];
@@ -241,16 +343,17 @@
_readabilityScript = [self _loadScriptForResource:@"Readability" withExtension:@"js"];
}
[userContentController _addUserScriptImmediately:_readabilityScript];
[userContentController __addUserScriptImmediately:_readabilityScript];
NSString *script = @""
"var documentClone = document.cloneNode(true);"
"var article = new Readability(documentClone).parse();"
"article.content";
os_log_t log = _log;
[_webView evaluateJavaScript:script completionHandler:^(NSString *result, NSError * _Nullable error) {
if (error != nil) {
NSLog(@"Bridge: Readability error: %@", error.localizedDescription);
os_log_error(log, "Bridge: Readability error: %@", error.localizedDescription);
} else {
completionBlock(result);
}

View File

@@ -77,6 +77,10 @@ static CGFloat RoundToScale(CGFloat v, CGFloat s) {
+ (UIImage *)iconRepresentationForPolicyType:(SBRScriptOriginPolicyType)policyType withConfiguration:(nonnull SBRScriptPolicyIconConfiguration *)configuration
{
const CGSize size = [configuration size];
if (size.width < CGFLOAT_EPSILON || size.height < CGFLOAT_EPSILON) {
return nil;
}
UIFont *font = [UIFont boldSystemFontOfSize:size.height - 2];
NSDictionary<NSAttributedStringKey, id> *attrs = @{
NSFontAttributeName : font,

28
README.md Normal file
View File

@@ -0,0 +1,28 @@
# Attractor
Attractor is a web browser for iOS and macOS prioritizing security and aggresive content filtering, and some nifty useful features.
![](Screenshots/main.png)
## Security Modes
Attractor aggresively filters unwanted web content and prevents arbitrary code execution (JavaScript) by default. I created a special browser for this purpose. Philosophically speaking, I believe the web should primarily be used as a document viewer (as originally intended by [Tim Berners-Lee](https://en.wikipedia.org/wiki/World_wide_web)). Interactive web applications are fine, but the *default* mode should be document viewing, which is why this security model exists.
Attractor operates in five "security modes":
1. **Alpha** (Default) All JavaScript is blocked, as well as web fonts and iframes.
2. **Bravo** Only embedded scripts are allowed. This means any JavaScript enclosed in `<script>` tags. Often this is enough to allow form validation to occur without issue.
3. **Charlie** Allows external JavaScript, but only from the same security origin. Meaning, if browsing `buzzert.net`, only external scripts from the domain `buzzert.net` (or subdomains) are allowed to execute.
4. **Delta** Allows external JavaScript, but only from a curated list of common CDNs.
5. **Echo** All scripts are allowed.
## Other features
- Dark mode (a very good one that uses low-level stylesheet injection to prevent flicker)
- Tab syncing
- Share via Email
- Reader Mode
- Arbitrary zoom scale
- User-defined scripts and stylesheets via UI
- Custom redirect rules
- Catalyst and iPadOS support

View File

@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 70;
objects = {
/* Begin PBXBuildFile section */
@@ -27,10 +27,7 @@
1ADFF46C24C7DE54006DC7AE /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1ADFF46A24C7DE54006DC7AE /* LaunchScreen.storyboard */; };
1ADFF47424C7DE9C006DC7AE /* BrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF47324C7DE9C006DC7AE /* BrowserViewController.swift */; };
1ADFF47924C7DFF8006DC7AE /* BrowserView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF47824C7DFF8006DC7AE /* BrowserView.swift */; };
1ADFF48424C8C12F006DC7AE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1ADFF48324C8C12F006DC7AE /* Foundation.framework */; };
1ADFF48D24C8C176006DC7AE /* SBRProcessBundleBridge.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF48C24C8C176006DC7AE /* SBRProcessBundleBridge.m */; };
1ADFF4A724C8C271006DC7AE /* SBrowserProcessBundle.bundle in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 1ADFF48124C8C12F006DC7AE /* SBrowserProcessBundle.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
1ADFF4AA24C8D477006DC7AE /* SBRProcessPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4A924C8D477006DC7AE /* SBRProcessPlugin.m */; };
1ADFF4AE24C8ED32006DC7AE /* ResourcePolicyManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4AD24C8ED32006DC7AE /* ResourcePolicyManager.swift */; };
1ADFF4C024CA6964006DC7AE /* URLBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4BF24CA6964006DC7AE /* URLBar.swift */; };
1ADFF4C324CA6AF6006DC7AE /* Geometry.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4C224CA6AF6006DC7AE /* Geometry.swift */; };
@@ -40,6 +37,8 @@
1ADFF4CD24CBB0C8006DC7AE /* ScriptOriginPolicyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1ADFF4CC24CBB0C8006DC7AE /* ScriptOriginPolicyViewController.swift */; };
CD01D5A5254A10BB00189CDC /* TabBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD01D5A4254A10BB00189CDC /* TabBarView.swift */; };
CD01D5AB254A206D00189CDC /* TabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD01D5AA254A206D00189CDC /* TabBarViewController.swift */; };
CD15332F297B6798009A7F3A /* HistoryBrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD15332E297B6798009A7F3A /* HistoryBrowserViewController.swift */; };
CD153331297B6806009A7F3A /* HistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD153330297B6806009A7F3A /* HistoryView.swift */; };
CD16844D269E709400B8F8A5 /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD16844C269E709400B8F8A5 /* Box.swift */; };
CD19576D268BE95900E8089B /* GenericContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD19576C268BE95900E8089B /* GenericContentView.swift */; };
CD361CF6271A3718006E9CA5 /* SBRScriptPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = CD361CF5271A3718006E9CA5 /* SBRScriptPolicy.m */; };
@@ -57,10 +56,12 @@
CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */; };
CD853BD124E778B800D2BDCC /* History.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CD853BCF24E778B800D2BDCC /* History.xcdatamodeld */; };
CD853BD424E77BF900D2BDCC /* HistoryItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD853BD324E77BF900D2BDCC /* HistoryItem.swift */; };
CD8ACBC22DC9A2F7008BF856 /* Hacks.m in Sources */ = {isa = PBXBuildFile; fileRef = CD8ACBC12DC9A2F7008BF856 /* Hacks.m */; };
CD8DBE7B2A85D892006A0FE0 /* LayoutLatch.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD8DBE7A2A85D892006A0FE0 /* LayoutLatch.swift */; };
CD936A3B289DB3380093A1AC /* TabInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD936A3A289DB3380093A1AC /* TabInfo.swift */; };
CD936A3D289DB88B0093A1AC /* UIView+Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */; };
CD97CF9225D5BE6F00288FEE /* NavigationControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */; };
CD9B88C2272201E900DAAB7E /* SBRScriptPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = CD361CF5271A3718006E9CA5 /* SBRScriptPolicy.m */; };
CDACE18C2C5B09F00053AB29 /* StringUtilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDACE18B2C5B09F00053AB29 /* StringUtilities.swift */; };
CDAD9CE8263A2DF200FF7199 /* DocumentControlsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAD9CE7263A2DF200FF7199 /* DocumentControlsView.swift */; };
CDAD9CEA263A318F00FF7199 /* ShareableURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDAD9CE9263A318F00FF7199 /* ShareableURL.swift */; };
CDB6807D28B446FC007D787E /* ReaderSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB6807C28B446FC007D787E /* ReaderSceneDelegate.swift */; };
@@ -83,16 +84,6 @@
CDF34690276C14BD00FB3141 /* CodeEditorSettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDF3468F276C14BD00FB3141 /* CodeEditorSettingsViewController.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
1ADFF48E24C8C230006DC7AE /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 1ADFF45424C7DE53006DC7AE /* Project object */;
proxyType = 1;
remoteGlobalIDString = 1ADFF48024C8C12F006DC7AE;
remoteInfo = SBrowserProcessBundle;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
1ADFF4A124C8C25B006DC7AE /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
@@ -100,7 +91,6 @@
dstPath = "";
dstSubfolderSpec = 13;
files = (
1ADFF4A724C8C271006DC7AE /* SBrowserProcessBundle.bundle in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
@@ -131,16 +121,10 @@
1ADFF47324C7DE9C006DC7AE /* BrowserViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserViewController.swift; sourceTree = "<group>"; };
1ADFF47524C7DF20006DC7AE /* SBrowser.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SBrowser.entitlements; sourceTree = "<group>"; };
1ADFF47824C7DFF8006DC7AE /* BrowserView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserView.swift; sourceTree = "<group>"; };
1ADFF48124C8C12F006DC7AE /* SBrowserProcessBundle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SBrowserProcessBundle.bundle; sourceTree = BUILT_PRODUCTS_DIR; };
1ADFF48324C8C12F006DC7AE /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
1ADFF48624C8C12F006DC7AE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
1ADFF48A24C8C176006DC7AE /* SBrowser-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SBrowser-Bridging-Header.h"; sourceTree = "<group>"; };
1ADFF48B24C8C176006DC7AE /* SBRProcessBundleBridge.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBRProcessBundleBridge.h; sourceTree = "<group>"; };
1ADFF48C24C8C176006DC7AE /* SBRProcessBundleBridge.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SBRProcessBundleBridge.m; sourceTree = "<group>"; };
1ADFF4A824C8D476006DC7AE /* SBRProcessPlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBRProcessPlugin.h; sourceTree = "<group>"; };
1ADFF4A924C8D477006DC7AE /* SBRProcessPlugin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SBRProcessPlugin.m; sourceTree = "<group>"; };
1ADFF4AB24C8DF62006DC7AE /* SBRWebProcessDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBRWebProcessDelegate.h; sourceTree = "<group>"; };
1ADFF4AC24C8DFEE006DC7AE /* SBRWebProcessProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBRWebProcessProxy.h; sourceTree = "<group>"; };
1ADFF4AD24C8ED32006DC7AE /* ResourcePolicyManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResourcePolicyManager.swift; sourceTree = "<group>"; };
1ADFF4BF24CA6964006DC7AE /* URLBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLBar.swift; sourceTree = "<group>"; };
1ADFF4C224CA6AF6006DC7AE /* Geometry.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Geometry.swift; sourceTree = "<group>"; };
@@ -150,10 +134,13 @@
1ADFF4CC24CBB0C8006DC7AE /* ScriptOriginPolicyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptOriginPolicyViewController.swift; sourceTree = "<group>"; };
CD01D5A4254A10BB00189CDC /* TabBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarView.swift; sourceTree = "<group>"; };
CD01D5AA254A206D00189CDC /* TabBarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabBarViewController.swift; sourceTree = "<group>"; };
CD15332E297B6798009A7F3A /* HistoryBrowserViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryBrowserViewController.swift; sourceTree = "<group>"; };
CD153330297B6806009A7F3A /* HistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryView.swift; sourceTree = "<group>"; };
CD16844C269E709400B8F8A5 /* Box.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Box.swift; sourceTree = "<group>"; };
CD19576C268BE95900E8089B /* GenericContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GenericContentView.swift; sourceTree = "<group>"; };
CD361CF4271A3718006E9CA5 /* SBRScriptPolicy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SBRScriptPolicy.h; sourceTree = "<group>"; };
CD361CF5271A3718006E9CA5 /* SBRScriptPolicy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SBRScriptPolicy.m; sourceTree = "<group>"; };
CD3D6CED2DA9F8910099667F /* WebKitDefines.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WebKitDefines.h; sourceTree = "<group>"; };
CD470C4125DE056600AFBE0E /* BrowserViewController+WebKitDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+WebKitDelegate.swift"; sourceTree = "<group>"; };
CD470C4325DE070400AFBE0E /* BrowserViewController+Keyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BrowserViewController+Keyboard.swift"; sourceTree = "<group>"; };
CD7313E12705349700053347 /* ScriptPolicyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScriptPolicyViewController.swift; sourceTree = "<group>"; };
@@ -168,9 +155,13 @@
CD853BCD24E7763900D2BDCC /* BrowserHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BrowserHistory.swift; sourceTree = "<group>"; };
CD853BD024E778B800D2BDCC /* History.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = History.xcdatamodel; sourceTree = "<group>"; };
CD853BD324E77BF900D2BDCC /* HistoryItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryItem.swift; sourceTree = "<group>"; };
CD8ACBC02DC9A2F7008BF856 /* Hacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Hacks.h; sourceTree = "<group>"; };
CD8ACBC12DC9A2F7008BF856 /* Hacks.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Hacks.m; sourceTree = "<group>"; };
CD8DBE7A2A85D892006A0FE0 /* LayoutLatch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutLatch.swift; sourceTree = "<group>"; };
CD936A3A289DB3380093A1AC /* TabInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TabInfo.swift; sourceTree = "<group>"; };
CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+Utils.swift"; sourceTree = "<group>"; };
CD97CF9125D5BE6F00288FEE /* NavigationControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationControlsView.swift; sourceTree = "<group>"; };
CDACE18B2C5B09F00053AB29 /* StringUtilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringUtilities.swift; sourceTree = "<group>"; };
CDAD9CE7263A2DF200FF7199 /* DocumentControlsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentControlsView.swift; sourceTree = "<group>"; };
CDAD9CE9263A318F00FF7199 /* ShareableURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareableURL.swift; sourceTree = "<group>"; };
CDB6807C28B446FC007D787E /* ReaderSceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderSceneDelegate.swift; sourceTree = "<group>"; };
@@ -193,6 +184,10 @@
CDF3468F276C14BD00FB3141 /* CodeEditorSettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeEditorSettingsViewController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
CDB73F3F2DA9F2F100DF4FAB /* WebKit Headers */ = {isa = PBXFileSystemSynchronizedRootGroup; explicitFileTypes = {}; explicitFolders = (); path = "WebKit Headers"; sourceTree = "<group>"; };
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
1ADFF45924C7DE53006DC7AE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
@@ -201,14 +196,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
1ADFF47E24C8C12F006DC7AE /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
1ADFF48424C8C12F006DC7AE /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
@@ -275,7 +262,7 @@
children = (
CDB6808828B4569F007D787E /* LICENSE.txt */,
1ADFF45E24C7DE53006DC7AE /* App */,
1ADFF48524C8C12F006DC7AE /* SBrowserProcessBundle */,
CDB73F3F2DA9F2F100DF4FAB /* WebKit Headers */,
1ADFF48224C8C12F006DC7AE /* Frameworks */,
1ADFF45D24C7DE53006DC7AE /* Products */,
);
@@ -285,7 +272,6 @@
isa = PBXGroup;
children = (
1ADFF45C24C7DE53006DC7AE /* Attractor.app */,
1ADFF48124C8C12F006DC7AE /* SBrowserProcessBundle.bundle */,
);
name = Products;
sourceTree = "<group>";
@@ -302,6 +288,7 @@
CDCE2662251AA7FC007FE92A /* Document Controls UI */,
1AD3104125254FA300A4A952 /* Find on Page */,
CD7F2133265DACEE0001D042 /* Hacks */,
CD15332D297B6784009A7F3A /* History UI */,
CDC5DA3C25DB7A5500BA8D99 /* Reader View */,
CDB6807B28B4456B007D787E /* Scene Delegates */,
1ADFF4CE24CBBCBD006DC7AE /* Script Policy UI */,
@@ -326,6 +313,7 @@
1ADFF46824C7DE54006DC7AE /* Assets.xcassets */,
1ADFF46A24C7DE54006DC7AE /* LaunchScreen.storyboard */,
1ADFF46D24C7DE54006DC7AE /* Info.plist */,
CD3D6CED2DA9F8910099667F /* WebKitDefines.h */,
);
path = "Supporting Files";
sourceTree = "<group>";
@@ -358,18 +346,6 @@
name = Frameworks;
sourceTree = "<group>";
};
1ADFF48524C8C12F006DC7AE /* SBrowserProcessBundle */ = {
isa = PBXGroup;
children = (
1ADFF48624C8C12F006DC7AE /* Info.plist */,
1ADFF4AB24C8DF62006DC7AE /* SBRWebProcessDelegate.h */,
1ADFF4AC24C8DFEE006DC7AE /* SBRWebProcessProxy.h */,
1ADFF4A824C8D476006DC7AE /* SBRProcessPlugin.h */,
1ADFF4A924C8D477006DC7AE /* SBRProcessPlugin.m */,
);
path = SBrowserProcessBundle;
sourceTree = "<group>";
};
1ADFF4AF24C92E2F006DC7AE /* Web Process Bundle Bridge */ = {
isa = PBXGroup;
children = (
@@ -391,6 +367,8 @@
1AB88F0524D4D3A90006F850 /* UIGestureRecognizer+Actions.swift */,
CDEDD8A925D62ADB00862605 /* UITraitCollection+MacLike.swift */,
CD936A3C289DB88B0093A1AC /* UIView+Utils.swift */,
CD8DBE7A2A85D892006A0FE0 /* LayoutLatch.swift */,
CDACE18B2C5B09F00053AB29 /* StringUtilities.swift */,
);
path = Utilities;
sourceTree = "<group>";
@@ -406,6 +384,15 @@
path = "Script Policy UI";
sourceTree = "<group>";
};
CD15332D297B6784009A7F3A /* History UI */ = {
isa = PBXGroup;
children = (
CD15332E297B6798009A7F3A /* HistoryBrowserViewController.swift */,
CD153330297B6806009A7F3A /* HistoryView.swift */,
);
path = "History UI";
sourceTree = "<group>";
};
CD7A7E9B2686A99600E20BA3 /* Amber */ = {
isa = PBXGroup;
children = (
@@ -426,6 +413,8 @@
CD7F2133265DACEE0001D042 /* Hacks */ = {
isa = PBXGroup;
children = (
CD8ACBC02DC9A2F7008BF856 /* Hacks.h */,
CD8ACBC12DC9A2F7008BF856 /* Hacks.m */,
CD7F2134265DAD010001D042 /* MFMailComposeViewControllerFix.m */,
);
path = Hacks;
@@ -516,30 +505,12 @@
buildRules = (
);
dependencies = (
1ADFF48F24C8C230006DC7AE /* PBXTargetDependency */,
);
name = App;
productName = SBrowser;
productReference = 1ADFF45C24C7DE53006DC7AE /* Attractor.app */;
productType = "com.apple.product-type.application";
};
1ADFF48024C8C12F006DC7AE /* SBrowserProcessBundle */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1ADFF48724C8C12F006DC7AE /* Build configuration list for PBXNativeTarget "SBrowserProcessBundle" */;
buildPhases = (
1ADFF47D24C8C12F006DC7AE /* Sources */,
1ADFF47E24C8C12F006DC7AE /* Frameworks */,
1ADFF47F24C8C12F006DC7AE /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = SBrowserProcessBundle;
productName = SBrowserProcessBundle;
productReference = 1ADFF48124C8C12F006DC7AE /* SBrowserProcessBundle.bundle */;
productType = "com.apple.product-type.bundle";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
@@ -553,9 +524,6 @@
CreatedOnToolsVersion = 12.0;
LastSwiftMigration = 1200;
};
1ADFF48024C8C12F006DC7AE = {
CreatedOnToolsVersion = 12.0;
};
};
};
buildConfigurationList = 1ADFF45724C7DE53006DC7AE /* Build configuration list for PBXProject "SBrowser" */;
@@ -572,7 +540,6 @@
projectRoot = "";
targets = (
1ADFF45B24C7DE53006DC7AE /* App */,
1ADFF48024C8C12F006DC7AE /* SBrowserProcessBundle */,
);
};
/* End PBXProject section */
@@ -593,13 +560,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
1ADFF47F24C8C12F006DC7AE /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -611,6 +571,7 @@
1AD3104325254FB900A4A952 /* FindOnPageViewController.swift in Sources */,
1A03811424E73EB300826501 /* SegmentedReliefButton.swift in Sources */,
1A03811024E71CF000826501 /* ReliefButton.swift in Sources */,
CD8ACBC22DC9A2F7008BF856 /* Hacks.m in Sources */,
1A03811224E71EAA00826501 /* GradientView.swift in Sources */,
1ADFF4C024CA6964006DC7AE /* URLBar.swift in Sources */,
CDAD9CEA263A318F00FF7199 /* ShareableURL.swift in Sources */,
@@ -634,6 +595,7 @@
CDB6807D28B446FC007D787E /* ReaderSceneDelegate.swift in Sources */,
CDD0522425F8055700DD1771 /* SearchProvider.swift in Sources */,
CD853BD424E77BF900D2BDCC /* HistoryItem.swift in Sources */,
CD15332F297B6798009A7F3A /* HistoryBrowserViewController.swift in Sources */,
1ADFF48D24C8C176006DC7AE /* SBRProcessBundleBridge.m in Sources */,
1AB88F0624D4D3A90006F850 /* UIGestureRecognizer+Actions.swift in Sources */,
CD7313E4270534B800053347 /* ScriptPolicyViewControllerDelegate.swift in Sources */,
@@ -641,6 +603,7 @@
CD16844D269E709400B8F8A5 /* Box.swift in Sources */,
CD853BCE24E7763900D2BDCC /* BrowserHistory.swift in Sources */,
1A03810B24E71C5600826501 /* ToolbarButtonContainerView.swift in Sources */,
CD8DBE7B2A85D892006A0FE0 /* LayoutLatch.swift in Sources */,
CD7A7EA12686B2E600E20BA3 /* RedirectRulesSettingsViewController.swift in Sources */,
1ADFF4CB24CB8278006DC7AE /* ScriptControllerIconView.swift in Sources */,
CD7A8915251975B70075991E /* AutocompleteViewController.swift in Sources */,
@@ -654,6 +617,7 @@
CDAD9CE8263A2DF200FF7199 /* DocumentControlsView.swift in Sources */,
1ADFF4C924CA793E006DC7AE /* ToolbarViewController.swift in Sources */,
CD7A89172519872D0075991E /* KeyboardShortcuts.swift in Sources */,
CDACE18C2C5B09F00053AB29 /* StringUtilities.swift in Sources */,
1ADFF4CD24CBB0C8006DC7AE /* ScriptOriginPolicyViewController.swift in Sources */,
CDE6A30425F023BC00E912A4 /* AmberSettingsViewController.swift in Sources */,
1A14FC2824D26749009B3F83 /* Tab.swift in Sources */,
@@ -663,6 +627,7 @@
CD01D5AB254A206D00189CDC /* TabBarViewController.swift in Sources */,
1ADFF47924C7DFF8006DC7AE /* BrowserView.swift in Sources */,
CDCE2664251AA80F007FE92A /* DocumentControlViewController.swift in Sources */,
CD153331297B6806009A7F3A /* HistoryView.swift in Sources */,
CDF3468E276C105900FB3141 /* SettingsSceneDelegate.swift in Sources */,
1AB88EFF24D3BBA50006F850 /* TabPickerViewController.swift in Sources */,
CD19576D268BE95900E8089B /* GenericContentView.swift in Sources */,
@@ -672,25 +637,8 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
1ADFF47D24C8C12F006DC7AE /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
CD9B88C2272201E900DAAB7E /* SBRScriptPolicy.m in Sources */,
1ADFF4AA24C8D477006DC7AE /* SBRProcessPlugin.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
1ADFF48F24C8C230006DC7AE /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 1ADFF48024C8C12F006DC7AE /* SBrowserProcessBundle */;
targetProxy = 1ADFF48E24C8C230006DC7AE /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
1ADFF46A24C7DE54006DC7AE /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
@@ -756,11 +704,12 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
HEADER_SEARCH_PATHS = "\"WebKit Headers\"";
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos.internal;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
@@ -813,10 +762,11 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
HEADER_SEARCH_PATHS = "\"WebKit Headers\"";
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos.internal;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
@@ -830,10 +780,15 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "App/Supporting Files/SBrowser.entitlements";
CODE_SIGN_IDENTITY = "-";
CURRENT_PROJECT_VERSION = 4;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 5;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = DQQH5H6GBD;
INFOPLIST_FILE = "App/Supporting Files/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = Attractor;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -841,8 +796,11 @@
MARKETING_VERSION = 4.0;
PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.attractor;
PRODUCT_NAME = Attractor;
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "App/Supporting Files/SBrowser-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
@@ -857,10 +815,15 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "App/Supporting Files/SBrowser.entitlements";
CODE_SIGN_IDENTITY = "-";
CURRENT_PROJECT_VERSION = 4;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 5;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = DQQH5H6GBD;
INFOPLIST_FILE = "App/Supporting Files/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = Attractor;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
IPHONEOS_DEPLOYMENT_TARGET = 18.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
@@ -868,47 +831,17 @@
MARKETING_VERSION = 4.0;
PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.attractor;
PRODUCT_NAME = Attractor;
PROVISIONING_PROFILE_SPECIFIER = "";
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_OBJC_BRIDGING_HEADER = "App/Supporting Files/SBrowser-Bridging-Header.h";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2,6";
};
name = Release;
};
1ADFF48824C8C12F006DC7AE /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEAD_CODE_STRIPPING = YES;
INFOPLIST_FILE = SBrowserProcessBundle/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.SBrowserProcessBundle;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos.internal;
STRIP_INSTALLED_PRODUCT = NO;
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,6";
WRAPPER_EXTENSION = bundle;
};
name = Debug;
};
1ADFF48924C8C12F006DC7AE /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
DEAD_CODE_STRIPPING = YES;
INFOPLIST_FILE = SBrowserProcessBundle/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles";
PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.SBrowserProcessBundle;
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = iphoneos.internal;
SUPPORTS_MACCATALYST = YES;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
TARGETED_DEVICE_FAMILY = "1,2,6";
WRAPPER_EXTENSION = bundle;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
@@ -930,15 +863,6 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1ADFF48724C8C12F006DC7AE /* Build configuration list for PBXNativeTarget "SBrowserProcessBundle" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1ADFF48824C8C12F006DC7AE /* Debug */,
1ADFF48924C8C12F006DC7AE /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */

View File

@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1400"
LastUpgradeVersion = "1600"
version = "1.7">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
buildImplicitDependencies = "YES"
buildArchitectures = "Automatic">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
@@ -26,9 +27,8 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
shouldUseLaunchSchemeArgsEnv = "YES"
shouldAutocreateTestPlan = "YES">
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
@@ -39,8 +39,7 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
internalIOSLaunchStyle = "2">
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
@@ -51,13 +50,6 @@
ReferencedContainer = "container:SBrowser.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<AdditionalOptions>
<AdditionalOption
key = "MallocScribble"
value = ""
isEnabled = "YES">
</AdditionalOption>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
@@ -83,7 +75,4 @@
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
<InstallAction
buildConfiguration = "Release">
</InstallAction>
</Scheme>

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSPrincipalClass</key>
<string>SBRProcessPlugin</string>
</dict>
</plist>

View File

@@ -1,17 +0,0 @@
//
// SBRProcessPlugin.h
// SBrowserProcessBundle
//
// Created by James Magahern on 7/22/20.
//
#import <Foundation/Foundation.h>
#import <WebKit/WKWebProcessPlugIn.h>
NS_ASSUME_NONNULL_BEGIN
@interface SBRProcessPlugin : NSObject <WKWebProcessPlugIn>
@end
NS_ASSUME_NONNULL_END

View File

@@ -1,115 +0,0 @@
//
// SBRProcessPlugin.m
// SBrowserProcessBundle
//
// Created by James Magahern on 7/22/20.
//
#import "SBRProcessPlugin.h"
#import "SBRWebProcessDelegate.h"
#import "SBRWebProcessProxy.h"
#import "SBRScriptPolicy.h"
#import <WebKit/_WKRemoteObjectInterface.h>
#import <WebKit/_WKRemoteObjectRegistry.h>
#import <WebKit/WKWebProcessPlugInBrowserContextController.h>
#import <WebKit/WKWebProcessPlugInBrowserContextControllerPrivate.h>
#import <WebKit/WKWebProcessPlugInFrame.h>
#import <WebKit/WKWebProcessPlugInLoadDelegate.h>
@interface SBRProcessPlugin () <WKWebProcessPlugInLoadDelegate, SBRWebProcessProxy>
@property (nonatomic, strong) id<SBRWebProcessDelegate> processDelegate;
@property (nonatomic, assign) BOOL allScriptsAllowed;
@property (nonatomic, strong) NSMutableSet<NSString *> *allowedResourceOrigins;
@property (nonatomic, strong) NSDictionary<NSString *, NSNumber *> *policyTypeByOrigin;
@end
@implementation SBRProcessPlugin
+ (void)initialize
{
[super initialize];
NSLog(@"SBRProcessPlugin Initialized");
}
#pragma mark <SBRWebProcessProxy>
- (void)hello
{
NSLog(@"SBRProcessPlugin: Helloooooo");
}
- (void)syncAllowedResourceOrigins:(NSArray<NSString *> *)allowedOrigins
{
_allowedResourceOrigins = [NSMutableSet setWithArray:allowedOrigins];
}
- (void)syncPolicyTypes:(NSDictionary<NSString *,NSNumber *> *)policyTypes
{
_policyTypeByOrigin = policyTypes;
}
- (void)setAllScriptsAllowed:(BOOL)allScriptsAllowed
{
_allScriptsAllowed = allScriptsAllowed;
}
#pragma mark <WKWebProcessPlugIn>
- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController initializeWithObject:(id)initializationObject
{
_allowedResourceOrigins = [[plugInController parameters] valueForKey:SBRGetAllowedOriginsKey()];
_allScriptsAllowed = [[[plugInController parameters] valueForKey:SBRGetAllScriptsAllowedKey()] boolValue];
_policyTypeByOrigin = [[plugInController parameters] valueForKey:SBRGetPolicyTypeByOriginKey()];
NSLog(@"SBRProcessPlugin: %lu origins allowed, all scripts allowed: %@ ", (unsigned long)_allowedResourceOrigins.count, _allScriptsAllowed ? @"YES" : @"NO");
}
- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController didCreateBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController
{
_WKRemoteObjectInterface *proxyInterface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(SBRWebProcessProxy)];
[browserContextController._remoteObjectRegistry registerExportedObject:self interface:proxyInterface];
_WKRemoteObjectInterface *eventListenerInterface = [_WKRemoteObjectInterface remoteObjectInterfaceWithProtocol:@protocol(SBRWebProcessDelegate)];
self.processDelegate = [browserContextController._remoteObjectRegistry remoteObjectProxyWithInterface:eventListenerInterface];
browserContextController.loadDelegate = self;
[[self processDelegate] webProcessDidConnect];
}
#pragma mark <WKWebProcessPlugInLoadDelegate>
- (NSURLRequest *)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller frame:(WKWebProcessPlugInFrame *)frame willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
{
NSLog(@"SBRProcessPlugin: Sending request: %@", request);
if (_allowedResourceOrigins == nil) {
NSLog(@"Allowed resource origins should not be nil!!!!");
}
NSURL *requestURL = [request URL];
NSString *resourceOrigin = [requestURL host];
NSString *requestExtension = [requestURL pathExtension];
NSString *hostOrigin = [[[controller mainFrame] URL] host];
if (requestExtension.length > 0 && [requestExtension isEqualToString:@"js"]) {
NSNumber *policyType = [_policyTypeByOrigin objectForKey:hostOrigin];
NSLog(@"SBRProcessPlugin: Policy type for %@: %@", hostOrigin, policyType);
SBRScriptPolicy *policy = [[SBRScriptPolicy alloc] initWithSecurityOrigin:hostOrigin policyType:[policyType integerValue]];
if ([self allScriptsAllowed] || [policy allowsExternalJavaScriptResourceOrigin:resourceOrigin]) {
NSLog(@"SBRProcessPlugin: Policy allows script requestURL: %@", requestURL);
[[self processDelegate] webProcessDidAllowScriptWithOrigin:resourceOrigin];
} else {
NSLog(@"SBRProcessPlugin: Policy disallows script requestURL: %@", requestURL);
[[self processDelegate] webProcessDidBlockScriptWithOrigin:resourceOrigin];
request = nil;
}
}
return request;
}
@end

View File

@@ -1,16 +0,0 @@
//
// SBRWebProcessDelegate.h
// SBrowser
//
// Created by James Magahern on 7/22/20.
//
#import <Foundation/Foundation.h>
@protocol SBRWebProcessDelegate <NSObject>
- (void)webProcessDidConnect;
- (void)webProcessDidBlockScriptWithOrigin:(NSString *)origin;
- (void)webProcessDidAllowScriptWithOrigin:(NSString *)origin;
@end

View File

@@ -1,29 +0,0 @@
//
// SBRWebProcessProxy.h
// SBrowser
//
// Created by James Magahern on 7/22/20.
//
#import <Foundation/Foundation.h>
static inline NSString* SBRGetAllowedOriginsKey() {
return @"allowedOrigins";
}
static inline NSString* SBRGetAllScriptsAllowedKey() {
return @"allScriptsAllowed";
}
static inline NSString* SBRGetPolicyTypeByOriginKey() {
return @"policyTypeByOrigin";
}
@protocol SBRWebProcessProxy <NSObject>
- (void)hello;
- (void)setAllScriptsAllowed:(BOOL)allowed;
- (void)syncAllowedResourceOrigins:(NSArray<NSString *> *)allowedOrigins;
- (void)syncPolicyTypes:(NSDictionary<NSString *, NSNumber *> *)policyTypes;
@end

BIN
Screenshots/main.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 442 KiB

View File

@@ -0,0 +1,162 @@
/*
* Copyright (C) 2010-2017 Apple Inc. All rights reserved.
* Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WKBase_h
#define WKBase_h
#include <WebKit/WKDeclarationSpecifiers.h>
#include <stdint.h>
#include <WebKit/WKBaseMac.h>
/* WebKit2 shared types */
typedef uint32_t WKTypeID;
typedef const void* WKTypeRef;
typedef const struct OpaqueWKArray* WKArrayRef;
typedef struct OpaqueWKArray* WKMutableArrayRef;
typedef const struct OpaqueWKDictionary* WKDictionaryRef;
typedef struct OpaqueWKDictionary* WKMutableDictionaryRef;
typedef const struct OpaqueWKBoolean* WKBooleanRef;
typedef const struct OpaqueWKCertificateInfo* WKCertificateInfoRef;
typedef const struct OpaqueWKConnection* WKConnectionRef;
typedef const struct OpaqueWKContextMenuItem* WKContextMenuItemRef;
typedef const struct OpaqueWKData* WKDataRef;
typedef const struct OpaqueWKDouble* WKDoubleRef;
typedef const struct OpaqueWKError* WKErrorRef;
typedef const struct OpaqueWKGraphicsContext* WKGraphicsContextRef;
typedef const struct OpaqueWKImage* WKImageRef;
typedef const struct OpaqueWKPointRef* WKPointRef;
typedef const struct OpaqueWKRectRef* WKRectRef;
typedef const struct OpaqueWKSecurityOrigin* WKSecurityOriginRef;
typedef const struct OpaqueWKSerializedScriptValue* WKSerializedScriptValueRef;
typedef const struct OpaqueWKSizeRef* WKSizeRef;
typedef const struct OpaqueWKString* WKStringRef;
typedef const struct OpaqueWKUInt64* WKUInt64Ref;
typedef const struct OpaqueWKURL* WKURLRef;
typedef const struct OpaqueWKURLRequest* WKURLRequestRef;
typedef const struct OpaqueWKURLResponse* WKURLResponseRef;
typedef const struct OpaqueWKUserContentURLPattern* WKUserContentURLPatternRef;
typedef const struct OpaqueWKWebArchive* WKWebArchiveRef;
typedef const struct OpaqueWKWebArchiveResource* WKWebArchiveResourceRef;
/* WebKit2 main API types */
typedef const struct OpaqueWKApplicationCacheManager* WKApplicationCacheManagerRef;
typedef const struct OpaqueWKAuthenticationChallenge* WKAuthenticationChallengeRef;
typedef const struct OpaqueWKAuthenticationDecisionListener* WKAuthenticationDecisionListenerRef;
typedef const struct OpaqueWKBackForwardList* WKBackForwardListRef;
typedef const struct OpaqueWKBackForwardListItem* WKBackForwardListItemRef;
typedef const struct OpaqueWKResourceCacheManager* WKResourceCacheManagerRef;
typedef const struct OpaqueWKColorPickerResultListener* WKColorPickerResultListenerRef;
typedef const struct OpaqueWKContext* WKContextRef;
typedef const struct OpaqueWKContextConfiguration* WKContextConfigurationRef;
typedef const struct OpaqueWKContextMenuListener* WKContextMenuListenerRef;
typedef const struct OpaqueWKCookieManager* WKCookieManagerRef;
typedef const struct OpaqueWKCredential* WKCredentialRef;
typedef const struct OpaqueWKDownload* WKDownloadRef;
typedef const struct OpaqueWKExperimentalFeature* WKFeatureRef;
typedef const struct OpaqueWKFormSubmissionListener* WKFormSubmissionListenerRef;
typedef const struct OpaqueWKFrameHandle* WKFrameHandleRef;
typedef const struct OpaqueWKFrameInfo* WKFrameInfoRef;
typedef const struct OpaqueWKFrame* WKFrameRef;
typedef const struct OpaqueWKFramePolicyListener* WKFramePolicyListenerRef;
typedef const struct OpaqueWKGeolocationManager* WKGeolocationManagerRef;
typedef const struct OpaqueWKGeolocationPermissionRequest* WKGeolocationPermissionRequestRef;
typedef const struct OpaqueWKGeolocationPosition* WKGeolocationPositionRef;
typedef const struct OpaqueWKGrammarDetail* WKGrammarDetailRef;
typedef const struct OpaqueWKHTTPCookieStore* WKHTTPCookieStoreRef;
typedef const struct OpaqueWKHitTestResult* WKHitTestResultRef;
typedef const struct OpaqueWKIconDatabase* WKIconDatabaseRef;
typedef const struct OpaqueWKInspector* WKInspectorRef;
typedef const struct OpaqueWKInternalDebugFeature* WKInternalDebugFeatureRef;
typedef const struct OpaqueWKKeyValueStorageManager* WKKeyValueStorageManagerRef;
typedef const struct OpaqueWKMessageListener* WKMessageListenerRef;
typedef const struct OpaqueWKNavigationAction* WKNavigationActionRef;
typedef const struct OpaqueWKNavigationData* WKNavigationDataRef;
typedef const struct OpaqueWKNavigation* WKNavigationRef;
typedef const struct OpaqueWKNavigationResponse* WKNavigationResponseRef;
typedef const struct OpaqueWKNotification* WKNotificationRef;
typedef const struct OpaqueWKNotificationManager* WKNotificationManagerRef;
typedef const struct OpaqueWKNotificationPermissionRequest* WKNotificationPermissionRequestRef;
typedef const struct OpaqueWKNotificationProvider* WKNotificationProviderRef;
typedef const struct OpaqueWKOpenPanelParameters* WKOpenPanelParametersRef;
typedef const struct OpaqueWKOpenPanelResultListener* WKOpenPanelResultListenerRef;
typedef const struct OpaqueWKPage* WKPageRef;
typedef const struct OpaqueWKPageConfiguration* WKPageConfigurationRef;
typedef const struct OpaqueWKPageGroup* WKPageGroupRef;
typedef const struct OpaqueWKPreferences* WKPreferencesRef;
typedef const struct OpaqueWKProtectionSpace* WKProtectionSpaceRef;
typedef const struct OpaqueWKPageRunBeforeUnloadConfirmPanelResultListener* WKPageRunBeforeUnloadConfirmPanelResultListenerRef;
typedef const struct OpaqueWKPageRunJavaScriptAlertResultListener* WKPageRunJavaScriptAlertResultListenerRef;
typedef const struct OpaqueWKPageRunJavaScriptConfirmResultListener* WKPageRunJavaScriptConfirmResultListenerRef;
typedef const struct OpaqueWKPageRunJavaScriptPromptResultListener* WKPageRunJavaScriptPromptResultListenerRef;
typedef const struct OpaqueWKPageRequestStorageAccessConfirmResultListener* WKPageRequestStorageAccessConfirmResultListenerRef;
typedef const struct OpaqueWKResourceLoadStatisticsManager* WKResourceLoadStatisticsManagerRef;
typedef const struct OpaqueWKTextChecker* WKTextCheckerRef;
typedef const struct OpaqueWKSession* WKSessionRef;
typedef const struct OpaqueWKSessionState* WKSessionStateRef;
typedef const struct OpaqueWKUserContentController* WKUserContentControllerRef;
typedef const struct OpaqueWKUserContentExtensionStore* WKUserContentExtensionStoreRef;
typedef const struct OpaqueWKUserContentFilter* WKUserContentFilterRef;
typedef const struct OpaqueWKUserMediaPermissionCheck* WKUserMediaPermissionCheckRef;
typedef const struct OpaqueWKUserMediaPermissionRequest* WKUserMediaPermissionRequestRef;
typedef const struct OpaqueWKUserScript* WKUserScriptRef;
typedef const struct OpaqueWKViewportAttributes* WKViewportAttributesRef;
typedef const struct OpaqueWKWebsiteDataConfigurationStore* WKWebsiteDataStoreConfigurationRef;
typedef const struct OpaqueWKWebsiteDataStore* WKWebsiteDataStoreRef;
typedef const struct OpaqueWKWebsitePolicies* WKWebsitePoliciesRef;
typedef const struct OpaqueWKWindowFeatures* WKWindowFeaturesRef;
typedef const struct OpaqueWKSpeechRecognitionPermissionCallback* WKSpeechRecognitionPermissionCallbackRef;
typedef const struct OpaqueWKMediaKeySystemPermissionRequest* WKMediaKeySystemPermissionRequestRef;
typedef const struct OpaqueWKMediaKeySystemPermissionCallback* WKMediaKeySystemPermissionCallbackRef;
typedef const struct OpaqueWKQueryPermissionResultCallback* WKQueryPermissionResultCallbackRef;
/* WebKit2 Bundle types */
typedef const struct OpaqueWKBundle* WKBundleRef;
typedef const struct OpaqueWKBundleBackForwardList* WKBundleBackForwardListRef;
typedef const struct OpaqueWKBundleBackForwardListItem* WKBundleBackForwardListItemRef;
typedef const struct OpaqueWKBundleDOMCSSStyleDeclaration* WKBundleCSSStyleDeclarationRef;
typedef const struct OpaqueWKBundleDOMWindowExtension* WKBundleDOMWindowExtensionRef;
typedef const struct OpaqueWKBundleFileHandle* WKBundleFileHandleRef;
typedef const struct OpaqueWKBundleFrame* WKBundleFrameRef;
typedef const struct OpaqueWKBundleHitTestResult* WKBundleHitTestResultRef;
typedef const struct OpaqueWKBundleInspector* WKBundleInspectorRef;
typedef const struct OpaqueWKBundleNavigationAction* WKBundleNavigationActionRef;
typedef const struct OpaqueWKBundleNodeHandle* WKBundleNodeHandleRef;
typedef const struct OpaqueWKBundlePage* WKBundlePageRef;
typedef const struct OpaqueWKBundlePageBanner* WKBundlePageBannerRef;
typedef const struct OpaqueWKBundlePageGroup* WKBundlePageGroupRef;
typedef const struct OpaqueWKBundlePageOverlay* WKBundlePageOverlayRef;
typedef const struct OpaqueWKBundleRangeHandle* WKBundleRangeHandleRef;
typedef const struct OpaqueWKBundleScriptWorld* WKBundleScriptWorldRef;
#endif /* WKBase_h */

View File

@@ -0,0 +1,35 @@
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WKBaseMac_h
#define WKBaseMac_h
#ifndef WKBase_h
#error "Please #include \"WKBase.h\" instead of this file directly."
#endif
typedef const struct OpaqueWKObjCTypeWrapper* WKObjCTypeWrapperRef;
#endif /* WKBaseMac_h */

View File

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2010, 2011 Apple Inc. All rights reserved.
* Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WKDeclarationSpecifiers_h
#define WKDeclarationSpecifiers_h
#ifndef __has_declspec_attribute
#define __has_declspec_attribute(x) 0
#endif
#undef WK_EXPORT
#if defined(WK_NO_EXPORT)
#define WK_EXPORT
#elif defined(WIN32) || defined(_WIN32) || defined(__CC_ARM) || defined(__ARMCC__) || (__has_declspec_attribute(dllimport) && __has_declspec_attribute(dllexport))
#if defined(BUILDING_WebKit)
#define WK_EXPORT __declspec(dllexport)
#else
#define WK_EXPORT __declspec(dllimport)
#endif /* defined(BUILDING_WebKit) */
#elif defined(__GNUC__)
#define WK_EXPORT __attribute__((visibility("default")))
#else /* !defined(WK_NO_EXPORT) */
#define WK_EXPORT
#endif /* defined(WK_NO_EXPORT) */
#if !defined(WK_INLINE)
#if defined(__cplusplus)
#define WK_INLINE static inline
#elif defined(__GNUC__)
#define WK_INLINE static __inline__
#else
#define WK_INLINE static
#endif
#endif /* !defined(WK_INLINE) */
#ifndef __has_extension
#define __has_extension(x) 0
#endif
#if __has_extension(enumerator_attributes) && __has_extension(attribute_unavailable_with_message)
#define WK_C_DEPRECATED(message) __attribute__((deprecated(message)))
#else
#define WK_C_DEPRECATED(message)
#endif
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
#if __has_attribute(unavailable)
#define WK_UNAVAILABLE __attribute__((unavailable))
#else
#define WK_UNAVAILABLE
#endif
#endif /* WKDeclarationSpecifiers_h */

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef WKLayoutMode_h
#define WKLayoutMode_h
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
enum {
kWKLayoutModeViewSize = 0,
kWKLayoutModeFixedSize = 1,
kWKLayoutModeDynamicSizeComputedFromViewScale = 2,
kWKLayoutModeDynamicSizeComputedFromMinimumDocumentSize = 4
};
typedef uint32_t WKLayoutMode;
#ifdef __cplusplus
}
#endif
#endif /* WKLayoutMode_h */

View File

@@ -0,0 +1,149 @@
/*
* Copyright (C) 2014-2022 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <WebKit/WKBase.h>
#import <WebKit/WKProcessPool.h>
#import <WebKit/WKSecurityOrigin.h>
@class WKWebView;
@class WKWebsiteDataStore;
@class _WKAutomationSession;
@class _WKDownload;
@class _WKProcessPoolConfiguration;
@protocol _WKAutomationDelegate;
@protocol _WKDownloadDelegate;
@protocol _WKGeolocationCoreLocationProvider;
@interface WKProcessPool ()
- (instancetype)_initWithConfiguration:(_WKProcessPoolConfiguration *)configuration __attribute__((objc_method_family(init))) NS_DESIGNATED_INITIALIZER;
@end
@interface WKProcessPool (WKPrivate)
+ (WKProcessPool *)_sharedProcessPool;
+ (NSArray<WKProcessPool *> *)_allProcessPoolsForTesting WK_API_AVAILABLE(macos(10.14), ios(12.0));
@property (nonatomic, readonly) _WKProcessPoolConfiguration *_configuration;
- (void)_setAllowsSpecificHTTPSCertificate:(NSArray *)certificateChain forHost:(NSString *)host WK_API_DEPRECATED_WITH_REPLACEMENT("WKWebsiteDataStore._allowTLSCertificateChain:forHost:", macos(10.10, 12.0), ios(8.0, 15.0));
- (void)_setCanHandleHTTPSServerTrustEvaluation:(BOOL)value WK_API_DEPRECATED_WITH_REPLACEMENT("_WKWebsiteDataStoreConfiguration.fastServerTrustEvaluationEnabled", macos(10.11, 10.15.4), ios(9.0, 13.4));
- (id)_objectForBundleParameter:(NSString *)parameter;
- (void)_setObject:(id <NSCopying, NSSecureCoding>)object forBundleParameter:(NSString *)parameter;
// FIXME: This should be NSDictionary<NSString *, id <NSCopying, NSSecureCoding>>
- (void)_setObjectsForBundleParametersWithDictionary:(NSDictionary *)dictionary WK_API_AVAILABLE(macos(10.12), ios(10.0));
#if !TARGET_OS_IPHONE
- (void)_resetPluginLoadClientPolicies:(NSDictionary *)policies WK_API_AVAILABLE(macos(10.13));
@property (nonatomic, readonly, copy) NSDictionary *_pluginLoadClientPolicies WK_API_AVAILABLE(macos(10.13));
#endif
@property (nonatomic, weak, setter=_setDownloadDelegate:) id <_WKDownloadDelegate> _downloadDelegate WK_API_DEPRECATED_WITH_REPLACEMENT("WKDownload.downloadDelegate", macos(10.10, 12.0), ios(8.0, 15.0));
@property (nonatomic, weak, setter=_setAutomationDelegate:) id <_WKAutomationDelegate> _automationDelegate WK_API_AVAILABLE(macos(10.12), ios(10.0));
#if TARGET_OS_IPHONE
@property (nonatomic, setter=_setCoreLocationProvider:) id <_WKGeolocationCoreLocationProvider> _coreLocationProvider WK_API_AVAILABLE(ios(11.0));
#endif
+ (NSURL *)_websiteDataURLForContainerWithURL:(NSURL *)containerURL;
+ (NSURL *)_websiteDataURLForContainerWithURL:(NSURL *)containerURL bundleIdentifierIfNotInContainer:(NSString *)bundleIdentifier;
+ (void)_setWebProcessCountLimit:(unsigned)limit WK_API_AVAILABLE(macos(13.0), ios(16.0));
- (void)_warmInitialProcess WK_API_AVAILABLE(macos(10.12), ios(10.0));
- (void)_automationCapabilitiesDidChange WK_API_AVAILABLE(macos(10.12), ios(10.0));
- (void)_setAutomationSession:(_WKAutomationSession *)automationSession WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, copy, setter=_setJavaScriptConfigurationDirectory:) NSURL *_javaScriptConfigurationDirectory WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
- (void)_addSupportedPlugin:(NSString *) domain named:(NSString *) name withMimeTypes: (NSSet<NSString *> *) mimeTypes withExtensions: (NSSet<NSString *> *) extensions WK_API_AVAILABLE(macos(10.14), ios(12.0));
- (void)_clearSupportedPlugins WK_API_AVAILABLE(macos(10.14), ios(12.0));
- (void)_registerURLSchemeAsCanDisplayOnlyIfCanRequest:(NSString *)scheme WK_API_AVAILABLE(macos(10.14), ios(12.0));
- (void)_registerURLSchemeAsSecure:(NSString *)scheme WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (void)_registerURLSchemeAsBypassingContentSecurityPolicy:(NSString *)scheme WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (void)_setDomainRelaxationForbiddenForURLScheme:(NSString *)scheme WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (_WKDownload *)_downloadURLRequest:(NSURLRequest *)request websiteDataStore:(WKWebsiteDataStore *)dataStore originatingWebView:(WKWebView *)webView WK_API_DEPRECATED_WITH_REPLACEMENT("WKWebView _downloadRequest", macos(10.10, 12.0), ios(8.0, 15.0));
- (_WKDownload *)_resumeDownloadFromData:(NSData *)resumeData websiteDataStore:(WKWebsiteDataStore *)dataStore path:(NSString *)path originatingWebView:(WKWebView *)webView WK_API_DEPRECATED_WITH_REPLACEMENT("WKWebView.resumeDownloadFromResumeData:completionHandler:", macos(10.10, 12.0), ios(8.0, 15.0));
+ (void)_setLinkedOnOrAfterEverything WK_API_AVAILABLE(macos(13.0), ios(16.0));
// Test only. Should be called only while no web content processes are running.
- (void)_terminateServiceWorkers WK_API_AVAILABLE(macos(10.14), ios(12.0));
// Test only.
- (pid_t)_prewarmedProcessIdentifier WK_API_AVAILABLE(macos(10.15), ios(13.0));
- (void)_terminateAllWebContentProcesses;
// Test only.
- (size_t)_webProcessCount WK_API_AVAILABLE(macos(10.13), ios(11.0));
- (BOOL)_hasPrewarmedWebProcess WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (size_t)_webProcessCountIgnoringPrewarmed WK_API_AVAILABLE(macos(10.14), ios(12.0));
- (size_t)_webProcessCountIgnoringPrewarmedAndCached WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (size_t)_pluginProcessCount WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
- (size_t)_serviceWorkerProcessCount WK_API_AVAILABLE(macos(10.14), ios(12.0));
- (void)_makeNextWebProcessLaunchFailForTesting WK_API_AVAILABLE(macos(10.14), ios(12.0));
- (NSUInteger)_maximumSuspendedPageCount WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (NSUInteger)_processCacheCapacity WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (NSUInteger)_processCacheSize WK_API_AVAILABLE(macos(10.15), ios(13.0));
- (void)_clearWebProcessCache WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
- (void)_setUseSeparateServiceWorkerProcess:(BOOL)forceServiceWorkerProcess WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
- (pid_t)_gpuProcessIdentifier WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (BOOL)_hasAudibleMediaActivity WK_API_AVAILABLE(macos(13.0), ios(16.0));
- (BOOL)_requestWebProcessTermination:(pid_t)pid WK_API_AVAILABLE(macos(12.0), ios(15.0));
// Test only. Returns web processes running web pages (does not include web processes running service workers)
- (size_t)_webPageContentProcessCount WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
// Test only. Should be called before any web content processes are launched.
+ (void)_forceGameControllerFramework WK_API_AVAILABLE(macos(10.13), ios(11.0));
+ (void)_setLinkedOnOrAfterEverythingForTesting WK_API_AVAILABLE(macos(12.0), ios(15.0));
+ (void)_setLinkedOnOrBeforeEverythingForTesting WK_API_AVAILABLE(macos(12.0), ios(15.0));
+ (void)_setCaptivePortalModeEnabledGloballyForTesting:(BOOL)isEnabled WK_API_AVAILABLE(macos(13.0), ios(16.0));
+ (void)_clearCaptivePortalModeEnabledGloballyForTesting WK_API_AVAILABLE(macos(13.0), ios(16.0));
+ (BOOL)_lockdownModeEnabledGloballyForTesting WK_API_AVAILABLE(macos(13.0), ios(16.0));
- (void)_preconnectToServer:(NSURL *)serverURL WK_API_DEPRECATED_WITH_REPLACEMENT("WKWebView._preconnectToServer", macos(10.13.4, 10.15.4), ios(11.3, 13.4));
// Test only.
- (void)_getActivePagesOriginsInWebProcessForTesting:(pid_t)pid completionHandler:(void(^)(NSArray<NSString *> *))completionHandler WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (void)_clearPermanentCredentialsForProtectionSpace:(NSURLProtectionSpace *)protectionSpace WK_API_AVAILABLE(macos(10.15), ios(13.0));
@property (nonatomic, getter=_isCookieStoragePartitioningEnabled, setter=_setCookieStoragePartitioningEnabled:) BOOL _cookieStoragePartitioningEnabled WK_API_DEPRECATED("Partitioned cookies are no longer supported", macos(10.12.3, 10.14.4), ios(10.3, 12.2));
- (WKNotificationManagerRef)_notificationManagerForTesting;
// Test only.
- (void)_seedResourceLoadStatisticsForTestingWithFirstParty:(NSURL *)firstPartyURL thirdParty:(NSURL *)thirdPartyURL shouldScheduleNotification:(BOOL)shouldScheduleNotification completionHandler:(void(^)(void))completionHandler WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
- (void)_garbageCollectJavaScriptObjectsForTesting WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (size_t)_numberOfConnectedGamepadsForTesting WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (size_t)_numberOfConnectedHIDGamepadsForTesting WK_API_AVAILABLE(macos(11.0), ios(15.0));
- (size_t)_numberOfConnectedGameControllerFrameworkGamepadsForTesting WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (void)_setUsesOnlyHIDGamepadProviderForTesting:(BOOL)usesHIDProvider WK_API_AVAILABLE(macos(11.0), ios(14.0));
@end

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <WebKit/WKUserContentController.h>
@class WKContentWorld;
@class WKUserScript;
@class _WKUserContentFilter;
@class _WKUserContentWorld;
@class _WKUserStyleSheet;
@interface WKUserContentController (WKPrivate)
- (void)_removeUserScript:(WKUserScript *)userScript WK_API_AVAILABLE(macos(10.12), ios(10.0));
- (void)_removeAllUserScriptsAssociatedWithContentWorld:(WKContentWorld *)contentWorld WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (void)_addUserScriptImmediately:(WKUserScript *)userScript WK_API_AVAILABLE(macos(10.14), ios(12.0));
// FIXME: Remove this once rdar://100785999 is unblocked.
- (void)_addUserContentFilter:(_WKUserContentFilter *)userContentFilter WK_API_DEPRECATED_WITH_REPLACEMENT("addContentRuleList", macos(10.11, 13.3), ios(9.0, 16.4));
- (void)_removeUserContentFilter:(NSString *)userContentFilterName WK_API_AVAILABLE(macos(10.11), ios(9.0));
- (void)_removeAllUserContentFilters WK_API_AVAILABLE(macos(10.11), ios(9.0));
- (void)_addContentRuleList:(WKContentRuleList *)contentRuleList extensionBaseURL:(NSURL *)extensionBaseURL WK_API_AVAILABLE(macos(13.0), ios(16.0));
@property (nonatomic, readonly, copy) NSArray<_WKUserStyleSheet *> *_userStyleSheets WK_API_AVAILABLE(macos(10.12), ios(10.0));
- (void)_addUserStyleSheet:(_WKUserStyleSheet *)userStyleSheet WK_API_AVAILABLE(macos(10.12), ios(10.0));
- (void)_removeUserStyleSheet:(_WKUserStyleSheet *)userStyleSheet WK_API_AVAILABLE(macos(10.12), ios(10.0));
- (void)_removeAllUserStyleSheets WK_API_AVAILABLE(macos(10.12), ios(10.0));
- (void)_removeAllUserStyleSheetsAssociatedWithContentWorld:(WKContentWorld *)contentWorld WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (void)_addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name userContentWorld:(_WKUserContentWorld *)userContentWorld WK_API_DEPRECATED_WITH_REPLACEMENT("_addScriptMessageHandler:name:contentWorld:", macos(10.11, 11.0), ios(9.0, 14.0));
- (void)_addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name contentWorld:(WKContentWorld *)contentWorld;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- (void)_removeScriptMessageHandlerForName:(NSString *)name userContentWorld:(_WKUserContentWorld *)userContentWorld;
- (void)_removeAllScriptMessageHandlersAssociatedWithUserContentWorld:(_WKUserContentWorld *)userContentWorld;
#pragma clang diagnostic pop
@end

View File

@@ -0,0 +1,47 @@
/*
* Copyright (C) 2012-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <WebKit/WKFoundation.h>
#import <Foundation/Foundation.h>
#import <WebKit/WKBase.h>
@class WKWebProcessPlugInController;
@class WKWebProcessPlugInBrowserContextController;
@protocol WKWebProcessPlugIn <NSObject>
@optional
- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController initializeWithObject:(id)initializationObject;
- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController didCreateBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController;
- (void)webProcessPlugIn:(WKWebProcessPlugInController *)plugInController willDestroyBrowserContextController:(WKWebProcessPlugInBrowserContextController *)browserContextController;
- (NSArray *)additionalClassesForParameterCoder;
@end
@interface WKWebProcessPlugInController : NSObject
- (void)extendClassesForParameterCoder:(NSArray *)classes;
@property (readonly) id parameters;
@end

View File

@@ -0,0 +1,45 @@
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <WebKit/WKFoundation.h>
#import <Foundation/Foundation.h>
@class WKDOMDocument;
@class WKDOMRange;
@class WKWebProcessPlugInFrame;
@protocol WKWebProcessPlugInLoadDelegate;
@interface WKWebProcessPlugInBrowserContextController : NSObject
@property (readonly) WKDOMDocument *mainFrameDocument;
@property (readonly) WKDOMRange *selectedRange;
@property (readonly) WKWebProcessPlugInFrame *mainFrame;
@property (weak) id <WKWebProcessPlugInLoadDelegate> loadDelegate;
@end

View File

@@ -0,0 +1,54 @@
/*
* Copyright (C) 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <WebKit/WKWebProcessPlugInBrowserContextController.h>
#import <WebKit/WKBase.h>
@class WKBrowsingContextHandle;
@class _WKRemoteObjectRegistry;
@protocol WKWebProcessPlugInEditingDelegate;
@protocol WKWebProcessPlugInFormDelegatePrivate;
@interface WKWebProcessPlugInBrowserContextController (WKPrivate)
@property (nonatomic, readonly) WKBundlePageRef _bundlePageRef;
@property (nonatomic, readonly) WKBrowsingContextHandle *handle;
@property (nonatomic, readonly) _WKRemoteObjectRegistry *_remoteObjectRegistry;
@property (weak, setter=_setFormDelegate:) id <WKWebProcessPlugInFormDelegatePrivate> _formDelegate;
@property (weak, setter=_setEditingDelegate:) id <WKWebProcessPlugInEditingDelegate> _editingDelegate API_AVAILABLE(macos(10.12.3), ios(10.3));
@property (nonatomic, readonly) BOOL _usesNonPersistentWebsiteDataStore;
@property (nonatomic, readonly) NSString *_groupIdentifier API_AVAILABLE(macos(12.0), ios(15.0));
+ (instancetype)lookUpBrowsingContextFromHandle:(WKBrowsingContextHandle *)handle;
@end

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <WebKit/WKFoundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>
@class _WKFrameHandle;
@class WKWebProcessPlugInCSSStyleDeclarationHandle;
@class WKWebProcessPlugInHitTestResult;
@class WKWebProcessPlugInNodeHandle;
@class WKWebProcessPlugInRangeHandle;
@class WKWebProcessPlugInScriptWorld;
typedef NS_OPTIONS(NSUInteger, WKHitTestOptions) {
WKHitTestOptionAllowUserAgentShadowRootContent = 1 << 0,
};
@interface WKWebProcessPlugInFrame : NSObject
@property (nonatomic, readonly) NSURL *URL;
@property (nonatomic, readonly) NSArray *childFrames;
@property (nonatomic, readonly) BOOL containsAnyFormElements;
@property (nonatomic, readonly) BOOL isMainFrame;
@property (nonatomic, readonly) _WKFrameHandle *handle;
// Returns URLs ordered by resolution in descending order.
// FIXME: These should be tagged nonnull.
@property (nonatomic, readonly) NSArray<NSURL *> *appleTouchIconURLs API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, readonly) NSArray<NSURL *> *faviconURLs API_AVAILABLE(macos(10.12), ios(10.0));
- (JSContext *)jsContextForWorld:(WKWebProcessPlugInScriptWorld *)world;
- (JSContext *)jsContextForServiceWorkerWorld:(WKWebProcessPlugInScriptWorld *)world;
- (WKWebProcessPlugInHitTestResult *)hitTest:(CGPoint)point;
- (WKWebProcessPlugInHitTestResult *)hitTest:(CGPoint)point options:(WKHitTestOptions)options API_AVAILABLE(macos(12.0), ios(15.0));
- (JSValue *)jsCSSStyleDeclarationForCSSStyleDeclarationHandle:(WKWebProcessPlugInCSSStyleDeclarationHandle *)cssStyleDeclarationHandle inWorld:(WKWebProcessPlugInScriptWorld *)world API_AVAILABLE(macos(13.0), ios(16.0));
- (JSValue *)jsNodeForNodeHandle:(WKWebProcessPlugInNodeHandle *)nodeHandle inWorld:(WKWebProcessPlugInScriptWorld *)world;
- (JSValue *)jsRangeForRangeHandle:(WKWebProcessPlugInRangeHandle *)rangeHandle inWorld:(WKWebProcessPlugInScriptWorld *)world API_AVAILABLE(macos(10.12.3), ios(10.3));
@end

View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <Foundation/Foundation.h>
#import <WebKit/_WKRenderingProgressEvents.h>
#import <WebKit/_WKSameDocumentNavigationType.h>
@class WKWebProcessPlugInBrowserContextController;
@class WKWebProcessPlugInFrame;
@class WKWebProcessPlugInScriptWorld;
@protocol WKWebProcessPlugInLoadDelegate <NSObject>
@optional
// Frame loading
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller didStartProvisionalLoadForFrame:(WKWebProcessPlugInFrame *)frame;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller didReceiveServerRedirectForProvisionalLoadForFrame:(WKWebProcessPlugInFrame *)frame;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller didCommitLoadForFrame:(WKWebProcessPlugInFrame *)frame;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller didFinishDocumentLoadForFrame:(WKWebProcessPlugInFrame *)frame;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller didFailProvisionalLoadWithErrorForFrame:(WKWebProcessPlugInFrame *)frame error:(NSError *)error;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller didFailLoadWithErrorForFrame:(WKWebProcessPlugInFrame *)frame error:(NSError *)error;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller didFinishLoadForFrame:(WKWebProcessPlugInFrame *)frame;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller didSameDocumentNavigation:(_WKSameDocumentNavigationType)navigationType forFrame:(WKWebProcessPlugInFrame *)frame;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller didClearWindowObjectForFrame:(WKWebProcessPlugInFrame *)frame inScriptWorld:(WKWebProcessPlugInScriptWorld *)scriptWorld;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller globalObjectIsAvailableForFrame:(WKWebProcessPlugInFrame *)frame inScriptWorld:(WKWebProcessPlugInScriptWorld *)scriptWorld;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller serviceWorkerGlobalObjectIsAvailableForFrame:(WKWebProcessPlugInFrame *)frame inScriptWorld:(WKWebProcessPlugInScriptWorld *)scriptWorld;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller willInjectUserScriptForFrame:(WKWebProcessPlugInFrame *)frame inScriptWorld:(WKWebProcessPlugInScriptWorld *)scriptWorld;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller didRemoveFrameFromHierarchy:(WKWebProcessPlugInFrame *)frame;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller didHandleOnloadEventsForFrame:(WKWebProcessPlugInFrame *)frame;
// Layout
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller didLayoutForFrame:(WKWebProcessPlugInFrame *)frame;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller renderingProgressDidChange:(_WKRenderingProgressEvents)events;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController*)controller didFirstVisuallyNonEmptyLayoutForFrame:(WKWebProcessPlugInFrame *)frame;
- (_WKRenderingProgressEvents)webProcessPlugInBrowserContextControllerRenderingProgressEvents:(WKWebProcessPlugInBrowserContextController *)controller;
// Resource loading
- (NSURLRequest *)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller frame:(WKWebProcessPlugInFrame *)frame willSendRequestForResource:(uint64_t)resource request:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse;
- (NSURLRequest *)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller frame:(WKWebProcessPlugInFrame *)frame willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller frame:(WKWebProcessPlugInFrame *)frame didInitiateLoadForResource:(uint64_t)resource request:(NSURLRequest *)request pageIsProvisionallyLoading:(BOOL)pageIsProvisionallyLoading;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller frame:(WKWebProcessPlugInFrame *)frame didInitiateLoadForResource:(uint64_t)resource request:(NSURLRequest *)request;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller frame:(WKWebProcessPlugInFrame *)frame didReceiveResponse:(NSURLResponse *)response forResource:(uint64_t)resource;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller frame:(WKWebProcessPlugInFrame *)frame didFinishLoadForResource:(uint64_t)resource;
- (void)webProcessPlugInBrowserContextController:(WKWebProcessPlugInBrowserContextController *)controller frame:(WKWebProcessPlugInFrame *)frame didFailLoadForResource:(uint64_t)resource error:(NSError *)error;
@end

View File

@@ -0,0 +1,173 @@
/*
* Copyright (C) 2014-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <WebKit/WKBase.h>
#import <WebKit/WKWebViewConfiguration.h>
#if TARGET_OS_IPHONE
typedef NS_ENUM(NSUInteger, _WKDragLiftDelay) {
_WKDragLiftDelayShort = 0,
_WKDragLiftDelayMedium,
_WKDragLiftDelayLong
} WK_API_AVAILABLE(ios(11.0));
typedef NS_ENUM(NSUInteger, _WKAttributionOverrideTesting) {
_WKAttributionOverrideTestingNoOverride = 0,
_WKAttributionOverrideTestingAppInitiated,
_WKAttributionOverrideTestingUserInitiated
} WK_API_AVAILABLE(ios(15.0));
@protocol _UIClickInteractionDriving;
#endif
typedef NS_ENUM(NSUInteger, _WKContentSecurityPolicyModeForExtension) {
_WKContentSecurityPolicyModeForExtensionNone = 0,
_WKContentSecurityPolicyModeForExtensionManifestV2,
_WKContentSecurityPolicyModeForExtensionManifestV3
} WK_API_AVAILABLE(macos(13.0), ios(16.0));
@class WKWebView;
@class _WKApplicationManifest;
@class _WKVisitedLinkStore;
@class _WKWebExtensionController;
@interface WKWebViewConfiguration (WKPrivate)
@property (nonatomic, weak, setter=_setRelatedWebView:) WKWebView *_relatedWebView;
@property (nonatomic, weak, setter=_setWebViewToCloneSessionStorageFrom:) WKWebView *_webViewToCloneSessionStorageFrom;
@property (nonatomic, copy, setter=_setGroupIdentifier:) NSString *_groupIdentifier;
@property (nonatomic, strong, setter=_setVisitedLinkStore:) _WKVisitedLinkStore *_visitedLinkStore;
@property (nonatomic, strong, readonly) _WKWebExtensionController *_strongWebExtensionController;
@property (nonatomic, weak, setter=_setWeakWebExtensionController:) _WKWebExtensionController *_weakWebExtensionController;
@property (nonatomic, strong, setter=_setWebExtensionController:) _WKWebExtensionController *_webExtensionController;
@property (nonatomic, weak, setter=_setAlternateWebViewForNavigationGestures:) WKWebView *_alternateWebViewForNavigationGestures;
@property (nonatomic, setter=_setRespectsImageOrientation:) BOOL _respectsImageOrientation WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setPrintsBackgrounds:) BOOL _printsBackgrounds WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setIncrementalRenderingSuppressionTimeout:) NSTimeInterval _incrementalRenderingSuppressionTimeout WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setAllowsJavaScriptMarkup:) BOOL _allowsJavaScriptMarkup WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setConvertsPositionStyleOnCopy:) BOOL _convertsPositionStyleOnCopy WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setAllowsMetaRefresh:) BOOL _allowsMetaRefresh WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setAllowUniversalAccessFromFileURLs:) BOOL _allowUniversalAccessFromFileURLs WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setAllowTopNavigationToDataURLs:) BOOL _allowTopNavigationToDataURLs WK_API_AVAILABLE(macos(11.0), ios(14.0));
@property (nonatomic, setter=_setNeedsStorageAccessFromFileURLsQuirk:) BOOL _needsStorageAccessFromFileURLsQuirk WK_API_AVAILABLE(macos(10.12.3), ios(10.3));
@property (nonatomic, setter=_setMainContentUserGestureOverrideEnabled:) BOOL _mainContentUserGestureOverrideEnabled WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setInvisibleAutoplayNotPermitted:) BOOL _invisibleAutoplayNotPermitted WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setMediaDataLoadsAutomatically:) BOOL _mediaDataLoadsAutomatically WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setAttachmentElementEnabled:) BOOL _attachmentElementEnabled WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setAttachmentWideLayoutEnabled:) BOOL _attachmentWideLayoutEnabled WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
@property (nonatomic, setter=_setAttachmentFileWrapperClass:) Class _attachmentFileWrapperClass WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
@property (nonatomic, setter=_setInitialCapitalizationEnabled:) BOOL _initialCapitalizationEnabled WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setApplePayEnabled:) BOOL _applePayEnabled WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, setter=_setWaitsForPaintAfterViewDidMoveToWindow:) BOOL _waitsForPaintAfterViewDidMoveToWindow WK_API_AVAILABLE(macos(10.12.3), ios(10.3));
@property (nonatomic, setter=_setControlledByAutomation:, getter=_isControlledByAutomation) BOOL _controlledByAutomation WK_API_AVAILABLE(macos(10.12.3), ios(10.3));
@property (nonatomic, setter=_setApplicationManifest:) _WKApplicationManifest *_applicationManifest WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
@property (nonatomic, setter=_setColorFilterEnabled:) BOOL _colorFilterEnabled WK_API_AVAILABLE(macos(10.14), ios(12.0));
@property (nonatomic, setter=_setIncompleteImageBorderEnabled:) BOOL _incompleteImageBorderEnabled WK_API_AVAILABLE(macos(10.14), ios(12.0));
@property (nonatomic, setter=_setDrawsBackground:) BOOL _drawsBackground WK_API_AVAILABLE(macos(10.14), ios(12.0));
@property (nonatomic, setter=_setShouldDeferAsynchronousScriptsUntilAfterDocumentLoad:) BOOL _shouldDeferAsynchronousScriptsUntilAfterDocumentLoad WK_API_AVAILABLE(macos(10.14), ios(12.0));
@property (nonatomic, readonly) WKWebsiteDataStore *_websiteDataStoreIfExists WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
@property (nonatomic, copy, setter=_setCORSDisablingPatterns:) NSArray<NSString *> *_corsDisablingPatterns WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
@property (nonatomic, copy, setter=_setMaskedURLSchemes:) NSSet<NSString *> *_maskedURLSchemes WK_API_AVAILABLE(macos(13.0), ios(16.0));
@property (nonatomic, setter=_setDeferrableUserScriptsShouldWaitUntilNotification:) BOOL _deferrableUserScriptsShouldWaitUntilNotification WK_API_AVAILABLE(macos(11.0), ios(14.0));
@property (nonatomic, setter=_setCrossOriginAccessControlCheckEnabled:) BOOL _crossOriginAccessControlCheckEnabled WK_API_AVAILABLE(macos(11.0), ios(14.0));
@property (nonatomic, setter=_setLoadsFromNetwork:) BOOL _loadsFromNetwork WK_API_DEPRECATED_WITH_REPLACEMENT("_allowedNetworkHosts", macos(11.0, 12.0), ios(14.0, 15.0));
@property (nonatomic, copy, setter=_setAllowedNetworkHosts:) NSSet<NSString *> *_allowedNetworkHosts WK_API_AVAILABLE(macos(12.0), ios(15.0));
@property (nonatomic, setter=_setLoadsSubresources:) BOOL _loadsSubresources WK_API_AVAILABLE(macos(11.0), ios(14.0));
@property (nonatomic, setter=_setIgnoresAppBoundDomains:) BOOL _ignoresAppBoundDomains WK_API_AVAILABLE(macos(11.0), ios(14.0));
#if TARGET_OS_IPHONE
@property (nonatomic, setter=_setClientNavigationsRunAtForegroundPriority:) BOOL _clientNavigationsRunAtForegroundPriority WK_API_AVAILABLE(ios(13.4));
@property (nonatomic, setter=_setAlwaysRunsAtForegroundPriority:) BOOL _alwaysRunsAtForegroundPriority WK_API_DEPRECATED_WITH_REPLACEMENT("_clientNavigationsRunAtForegroundPriority", ios(9.0, 14.0));
@property (nonatomic, setter=_setInlineMediaPlaybackRequiresPlaysInlineAttribute:) BOOL _inlineMediaPlaybackRequiresPlaysInlineAttribute WK_API_AVAILABLE(ios(10.0));
@property (nonatomic, setter=_setAllowsInlineMediaPlaybackAfterFullscreen:) BOOL _allowsInlineMediaPlaybackAfterFullscreen WK_API_AVAILABLE(ios(10.0));
@property (nonatomic, setter=_setDragLiftDelay:) _WKDragLiftDelay _dragLiftDelay WK_API_AVAILABLE(ios(11.0));
@property (nonatomic, setter=_setLongPressActionsEnabled:) BOOL _longPressActionsEnabled WK_API_AVAILABLE(ios(12.0));
@property (nonatomic, setter=_setSystemPreviewEnabled:) BOOL _systemPreviewEnabled WK_API_AVAILABLE(ios(12.0));
@property (nonatomic, setter=_setShouldDecidePolicyBeforeLoadingQuickLookPreview:) BOOL _shouldDecidePolicyBeforeLoadingQuickLookPreview WK_API_AVAILABLE(ios(13.0));
@property (nonatomic, setter=_setCanShowWhileLocked:) BOOL _canShowWhileLocked WK_API_AVAILABLE(ios(13.0));
@property (nonatomic, setter=_setClickInteractionDriverForTesting:) id <_UIClickInteractionDriving> _clickInteractionDriverForTesting WK_API_AVAILABLE(ios(13.0));
@property (nonatomic, setter=_setAppInitiatedOverrideValueForTesting:) _WKAttributionOverrideTesting _appInitiatedOverrideValueForTesting WK_API_AVAILABLE(ios(15.0));
#else
@property (nonatomic, setter=_setShowsURLsInToolTips:) BOOL _showsURLsInToolTips WK_API_AVAILABLE(macos(10.12));
@property (nonatomic, setter=_setServiceControlsEnabled:) BOOL _serviceControlsEnabled WK_API_AVAILABLE(macos(10.12));
@property (nonatomic, setter=_setImageControlsEnabled:) BOOL _imageControlsEnabled WK_API_AVAILABLE(macos(13.0));
@property (nonatomic, setter=_setContextMenuQRCodeDetectionEnabled:) BOOL _contextMenuQRCodeDetectionEnabled WK_API_AVAILABLE(macos(WK_MAC_TBA));
@property (nonatomic, readwrite, setter=_setRequiresUserActionForEditingControlsManager:) BOOL _requiresUserActionForEditingControlsManager WK_API_AVAILABLE(macos(10.12));
@property (nonatomic, readwrite, setter=_setCPULimit:) double _cpuLimit WK_API_AVAILABLE(macos(10.13.4));
@property (nonatomic, readwrite, setter=_setPageGroup:) WKPageGroupRef _pageGroup WK_API_AVAILABLE(macos(10.13.4));
#endif
@property (nonatomic, setter=_setRequiresUserActionForAudioPlayback:) BOOL _requiresUserActionForAudioPlayback WK_API_DEPRECATED_WITH_REPLACEMENT("mediaTypesRequiringUserActionForPlayback", macos(10.12, 10.12), ios(10.0, 10.0));
@property (nonatomic, setter=_setRequiresUserActionForVideoPlayback:) BOOL _requiresUserActionForVideoPlayback WK_API_DEPRECATED_WITH_REPLACEMENT("mediaTypesRequiringUserActionForPlayback", macos(10.12, 10.12), ios(10.0, 10.0));
@property (nonatomic, setter=_setOverrideContentSecurityPolicy:) NSString *_overrideContentSecurityPolicy WK_API_AVAILABLE(macos(10.12.3), ios(10.3));
@property (nonatomic, setter=_setMediaContentTypesRequiringHardwareSupport:) NSString *_mediaContentTypesRequiringHardwareSupport WK_API_AVAILABLE(macos(10.13), ios(11.0));
@property (nonatomic, setter=_setLegacyEncryptedMediaAPIEnabled:) BOOL _legacyEncryptedMediaAPIEnabled WK_API_AVAILABLE(macos(10.13), ios(11.0));
@property (nonatomic, setter=_setAllowMediaContentTypesRequiringHardwareSupportAsFallback:) BOOL _allowMediaContentTypesRequiringHardwareSupportAsFallback WK_API_AVAILABLE(macos(10.13), ios(11.0));
@property (nonatomic, setter=_setMediaCaptureEnabled:) BOOL _mediaCaptureEnabled WK_API_AVAILABLE(macos(12.0), ios(15.0));
// The input of this SPI is an array of image UTI (Uniform Type Identifier).
@property (nonatomic, copy, setter=_setAdditionalSupportedImageTypes:) NSArray<NSString *> *_additionalSupportedImageTypes WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
@property (nonatomic, setter=_setUndoManagerAPIEnabled:) BOOL _undoManagerAPIEnabled WK_API_AVAILABLE(macos(10.15), ios(13.0));
@property (nonatomic, setter=_setShouldRelaxThirdPartyCookieBlocking:) BOOL _shouldRelaxThirdPartyCookieBlocking WK_API_AVAILABLE(macos(11.0), ios(14.0));
@property (nonatomic, setter=_setProcessDisplayName:) NSString *_processDisplayName WK_API_AVAILABLE(macos(11.0), ios(14.0));
@property (nonatomic, setter=_setAppHighlightsEnabled:) BOOL _appHighlightsEnabled WK_API_AVAILABLE(macos(12.0), ios(15.0));
@property (nonatomic, setter=_setAllowTestOnlyIPC:) BOOL _allowTestOnlyIPC WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
// The maximum Lab color difference allowed between two consecutive page top snapshots.
// Expects 0 (disables page top color sampling entirely) or any positive number.
@property (nonatomic, setter=_setSampledPageTopColorMaxDifference:) double _sampledPageTopColorMaxDifference WK_API_AVAILABLE(macos(12.0), ios(15.0));
// How far down the page the sampled page top color needs to extend in order to be considered valid.
// Expects 0 (the color doesn't need to continue into the page at all) or any positive number.
@property (nonatomic, setter=_setSampledPageTopColorMinHeight:) double _sampledPageTopColorMinHeight WK_API_AVAILABLE(macos(12.0), ios(15.0));
// Attributes network activity from this WKWebView to the app with this bundle.
@property (nonatomic, setter=_setAttributedBundleIdentifier:) NSString *_attributedBundleIdentifier;
@property (nonatomic, setter=_setContentSecurityPolicyModeForExtension:) _WKContentSecurityPolicyModeForExtension _contentSecurityPolicyModeForExtension WK_API_AVAILABLE(macos(13.0), ios(16.0));
@property (nonatomic, setter=_setMarkedTextInputEnabled:) BOOL _markedTextInputEnabled WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
@end
#if TARGET_OS_IPHONE
@interface WKWebViewConfiguration (WKPrivateDeprecated)
@property (nonatomic, setter=_setTextInteractionGesturesEnabled:) BOOL _textInteractionGesturesEnabled WK_API_DEPRECATED_WITH_REPLACEMENT("WKPreferences.textInteractionGesturesEnabled", ios(12.0, 15.0));
@end
#endif

View File

@@ -0,0 +1,770 @@
/*
* Copyright (C) 2014-2020 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#if TARGET_OS_IPHONE
#if __has_include(<UIKit/_UIFindInteraction.h>)
#import <UIKit/_UIFindInteraction.h>
#endif
#if __has_include(<UIKit/_UITextSearching.h>)
#import <UIKit/_UITextSearching.h>
#endif
#endif
#import <WebKit/WKDataDetectorTypes.h>
#import <WebKit/WKWebView.h>
#import <WebKit/_WKActivatedElementInfo.h>
#import <WebKit/_WKAttachment.h>
#import <WebKit/_WKFindOptions.h>
#import <WebKit/_WKLayoutMode.h>
#import <WebKit/_WKOverlayScrollbarStyle.h>
#import <WebKit/_WKRenderingProgressEvents.h>
typedef NS_ENUM(NSInteger, _WKPaginationMode) {
_WKPaginationModeUnpaginated,
_WKPaginationModeLeftToRight,
_WKPaginationModeRightToLeft,
_WKPaginationModeTopToBottom,
_WKPaginationModeBottomToTop,
} WK_API_AVAILABLE(macos(10.10), ios(8.0));
typedef NS_OPTIONS(NSUInteger, _WKMediaCaptureStateDeprecated) {
_WKMediaCaptureStateDeprecatedNone = 0,
_WKMediaCaptureStateDeprecatedActiveMicrophone = 1 << 0,
_WKMediaCaptureStateDeprecatedActiveCamera = 1 << 1,
_WKMediaCaptureStateDeprecatedMutedMicrophone = 1 << 2,
_WKMediaCaptureStateDeprecatedMutedCamera = 1 << 3,
} WK_API_AVAILABLE(macos(10.13), ios(11.0));
typedef NS_OPTIONS(NSUInteger, _WKMediaMutedState) {
_WKMediaNoneMuted = 0,
_WKMediaAudioMuted = 1 << 0,
_WKMediaCaptureDevicesMuted = 1 << 1,
_WKMediaScreenCaptureMuted = 1 << 2,
} WK_API_AVAILABLE(macos(10.13), ios(11.0));
typedef NS_OPTIONS(NSUInteger, _WKCaptureDevices) {
_WKCaptureDeviceMicrophone = 1 << 0,
_WKCaptureDeviceCamera = 1 << 1,
_WKCaptureDeviceDisplay = 1 << 2,
} WK_API_AVAILABLE(macos(10.13), ios(11.0));
typedef NS_OPTIONS(NSUInteger, _WKSelectionAttributes) {
_WKSelectionAttributeNoSelection = 0,
_WKSelectionAttributeIsCaret = 1 << 0,
_WKSelectionAttributeIsRange = 1 << 1,
} WK_API_AVAILABLE(macos(10.15), ios(13.0));
typedef NS_ENUM(NSInteger, _WKShouldOpenExternalURLsPolicy) {
_WKShouldOpenExternalURLsPolicyNotAllow,
_WKShouldOpenExternalURLsPolicyAllow,
_WKShouldOpenExternalURLsPolicyAllowExternalSchemesButNotAppLinks,
} WK_API_AVAILABLE(macos(12.0), ios(15.0));
#if TARGET_OS_IPHONE
typedef NS_ENUM(NSUInteger, _WKDragInteractionPolicy) {
_WKDragInteractionPolicyDefault = 0,
_WKDragInteractionPolicyAlwaysEnable,
_WKDragInteractionPolicyAlwaysDisable
} WK_API_AVAILABLE(ios(11.0));
#else
#import <WebKit/WKBase.h>
#endif
#if !TARGET_OS_IPHONE
typedef NS_ENUM(NSInteger, _WKImmediateActionType) {
_WKImmediateActionNone,
_WKImmediateActionLinkPreview,
_WKImmediateActionDataDetectedItem,
_WKImmediateActionLookupText,
_WKImmediateActionMailtoLink,
_WKImmediateActionTelLink
} WK_API_AVAILABLE(macos(10.12));
typedef NS_OPTIONS(NSUInteger, _WKRectEdge) {
_WKRectEdgeNone = 0,
_WKRectEdgeLeft = 1 << CGRectMinXEdge,
_WKRectEdgeTop = 1 << CGRectMinYEdge,
_WKRectEdgeRight = 1 << CGRectMaxXEdge,
_WKRectEdgeBottom = 1 << CGRectMaxYEdge,
_WKRectEdgeAll = _WKRectEdgeLeft | _WKRectEdgeTop | _WKRectEdgeRight | _WKRectEdgeBottom,
} WK_API_AVAILABLE(macos(10.13.4));
#endif
@class UIEventAttribution;
@class UITextInputTraits;
@class WKBrowsingContextHandle;
@class WKDownload;
@class WKFrameInfo;
@class WKSecurityOrigin;
@class WKWebpagePreferences;
@class _UIFindInteraction;
@class _WKApplicationManifest;
@class _WKDataTask;
@class _WKFrameHandle;
@class _WKFrameTreeNode;
@class _WKHitTestResult;
@class _WKInspector;
@class _WKRemoteObjectRegistry;
@class _WKSafeBrowsingWarning;
@class _WKSessionState;
@class _WKTextInputContext;
@class _WKTextManipulationConfiguration;
@class _WKTextManipulationItem;
@class _WKThumbnailView;
@class _WKWebViewPrintFormatter;
@protocol WKHistoryDelegatePrivate;
@protocol _WKAppHighlightDelegate;
@protocol _WKDiagnosticLoggingDelegate;
@protocol _WKFindDelegate;
@protocol _WKFullscreenDelegate;
@protocol _WKIconLoadingDelegate;
@protocol _WKInputDelegate;
@protocol _WKResourceLoadDelegate;
@protocol _WKTextManipulationDelegate;
@interface WKWebView (WKPrivate)
// FIXME: This should return a _WKRemoteObjectRegistry *.
@property (nonatomic, readonly) id _remoteObjectRegistry;
@property (nonatomic, readonly) WKBrowsingContextHandle *_handle;
@property (nonatomic, setter=_setObservedRenderingProgressEvents:) _WKRenderingProgressEvents _observedRenderingProgressEvents;
@property (nonatomic, weak, setter=_setHistoryDelegate:) id <WKHistoryDelegatePrivate> _historyDelegate;
@property (nonatomic, weak, setter=_setIconLoadingDelegate:) id <_WKIconLoadingDelegate> _iconLoadingDelegate;
@property (nonatomic, weak, setter=_setResourceLoadDelegate:) id <_WKResourceLoadDelegate> _resourceLoadDelegate WK_API_AVAILABLE(macos(11.0), ios(14.0));
@property (nonatomic, readonly) NSURL *_unreachableURL;
@property (nonatomic, readonly) NSURL *_mainFrameURL WK_API_AVAILABLE(macos(10.15), ios(13.0));
@property (nonatomic, readonly) NSURL *_resourceDirectoryURL WK_API_AVAILABLE(macos(10.15), ios(13.0));
- (void)_loadAlternateHTMLString:(NSString *)string baseURL:(NSURL *)baseURL forUnreachableURL:(NSURL *)unreachableURL;
- (WKNavigation *)_loadData:(NSData *)data MIMEType:(NSString *)MIMEType characterEncodingName:(NSString *)characterEncodingName baseURL:(NSURL *)baseURL userData:(id)userData WK_API_AVAILABLE(macos(10.12), ios(10.0));
- (WKNavigation *)_loadRequest:(NSURLRequest *)request shouldOpenExternalURLs:(BOOL)shouldOpenExternalURLs WK_API_AVAILABLE(macos(10.13), ios(11.0));
- (WKNavigation *)_loadRequest:(NSURLRequest *)request shouldOpenExternalURLsPolicy:(_WKShouldOpenExternalURLsPolicy)shouldOpenExternalURLsPolicy WK_API_AVAILABLE(macos(12.0), ios(15.0));
@property (nonatomic, readonly) NSArray *_certificateChain WK_API_DEPRECATED_WITH_REPLACEMENT("certificateChain", macos(10.10, 10.11), ios(8.0, 9.0));
@property (nonatomic, readonly) NSURL *_committedURL;
@property (nonatomic, readonly) NSString *_MIMEType;
@property (nonatomic, readonly) NSString *_userAgent WK_API_AVAILABLE(macos(10.11), ios(9.0));
@property (copy, setter=_setApplicationNameForUserAgent:) NSString *_applicationNameForUserAgent;
@property (copy, setter=_setCustomUserAgent:) NSString *_customUserAgent;
@property (nonatomic, readonly, getter=_isPlayingAudio) BOOL _playingAudio WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
@property (nonatomic, setter=_setUserContentExtensionsEnabled:) BOOL _userContentExtensionsEnabled WK_API_AVAILABLE(macos(10.11), ios(9.0));
@property (nonatomic, readonly) pid_t _webProcessIdentifier;
@property (nonatomic, readonly) pid_t _provisionalWebProcessIdentifier WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
@property (nonatomic, readonly) pid_t _gpuProcessIdentifier WK_API_AVAILABLE(macos(13.0), ios(16.0));
@property (nonatomic, getter=_isEditable, setter=_setEditable:) BOOL _editable WK_API_AVAILABLE(macos(10.11), ios(9.0));
/*! @abstract A Boolean value indicating whether any resource on the page
has been loaded over a connection using TLS 1.0 or TLS 1.1.
@discussion @link WKWebView @/link is key-value observing (KVO) compliant
for this property.
*/
@property (nonatomic, readonly) BOOL _negotiatedLegacyTLS WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
@property (nonatomic, readonly) BOOL _wasPrivateRelayed WK_API_AVAILABLE(macos(13.1), ios(16.2));
- (void)_frames:(void (^)(_WKFrameTreeNode *))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
// FIXME: Remove these once nobody is using them.
@property (nonatomic, readonly) NSData *_sessionStateData;
- (void)_restoreFromSessionStateData:(NSData *)sessionStateData;
@property (nonatomic, readonly) _WKSessionState *_sessionState;
- (WKNavigation *)_restoreSessionState:(_WKSessionState *)sessionState andNavigate:(BOOL)navigate;
- (_WKSessionState *)_sessionStateWithFilter:(BOOL (^)(WKBackForwardListItem *item))filter;
@property (nonatomic, setter=_setAllowsRemoteInspection:) BOOL _allowsRemoteInspection WK_API_DEPRECATED_WITH_REPLACEMENT("inspectable", macos(10.10, 13.3), ios(8.0, 16.4));
@property (nonatomic, copy, setter=_setRemoteInspectionNameOverride:) NSString *_remoteInspectionNameOverride WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, readonly) BOOL _isBeingInspected WK_API_AVAILABLE(macos(12.0), ios(15.0));
@property (nonatomic, readonly) _WKInspector *_inspector WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
@property (nonatomic, readonly) _WKFrameHandle *_mainFrame WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
@property (nonatomic, weak, setter=_setTextManipulationDelegate:) id <_WKTextManipulationDelegate> _textManipulationDelegate WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
- (void)_startTextManipulationsWithConfiguration:(_WKTextManipulationConfiguration *)configuration completion:(void(^)(void))completionHandler WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
- (void)_completeTextManipulation:(_WKTextManipulationItem *)item completion:(void(^)(BOOL success))completionHandler WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
- (void)_completeTextManipulationForItems:(NSArray<_WKTextManipulationItem *> *)items completion:(void(^)(NSArray<NSError *> *errors))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
@property (nonatomic, setter=_setAddsVisitedLinks:) BOOL _addsVisitedLinks;
@property (nonatomic, readonly) BOOL _networkRequestsInProgress;
@property (nonatomic, readonly, getter=_isShowingNavigationGestureSnapshot) BOOL _showingNavigationGestureSnapshot;
- (void)_close;
- (BOOL)_tryClose WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
- (BOOL)_isClosed WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
- (void)_updateWebpagePreferences:(WKWebpagePreferences *)webpagePreferences WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
- (void)_notifyUserScripts WK_API_AVAILABLE(macos(11.0), ios(14.0));
@property (nonatomic, readonly) BOOL _deferrableUserScriptsNeedNotification WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (void)_evaluateJavaScriptWithoutUserGesture:(NSString *)javaScriptString completionHandler:(void (^)(id, NSError *))completionHandler WK_API_AVAILABLE(macos(10.13), ios(11.0));
- (void)_evaluateJavaScript:(NSString *)javaScriptString inFrame:(WKFrameInfo *)frame inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^)(id, NSError * error))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (void)_evaluateJavaScript:(NSString *)javaScriptString withSourceURL:(NSURL *)sourceURL inFrame:(WKFrameInfo *)frame inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^)(id, NSError * error))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (void)_callAsyncJavaScript:(NSString *)functionBody arguments:(NSDictionary<NSString *, id> *)arguments inFrame:(WKFrameInfo *)frame inContentWorld:(WKContentWorld *)contentWorld completionHandler:(void (^)(id, NSError *error))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (BOOL)_allMediaPresentationsClosed WK_API_AVAILABLE(macos(12.0), ios(15.0));
@property (nonatomic, setter=_setLayoutMode:) _WKLayoutMode _layoutMode;
// For use with _layoutMode = _WKLayoutModeFixedSize:
@property (nonatomic, setter=_setFixedLayoutSize:) CGSize _fixedLayoutSize;
@property (nonatomic, setter=_setViewportSizeForCSSViewportUnits:) CGSize _viewportSizeForCSSViewportUnits WK_API_AVAILABLE(macos(10.13), ios(11.0));
@property (nonatomic, setter=_setViewScale:) CGFloat _viewScale WK_API_AVAILABLE(macos(10.11), ios(9.0));
@property (nonatomic, setter=_setMinimumEffectiveDeviceWidth:) CGFloat _minimumEffectiveDeviceWidth WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
@property (nonatomic, setter=_setBackgroundExtendsBeyondPage:) BOOL _backgroundExtendsBeyondPage WK_API_AVAILABLE(macos(10.13.4), ios(8.0));
- (_WKAttachment *)_insertAttachmentWithFilename:(NSString *)filename contentType:(NSString *)contentType data:(NSData *)data options:(_WKAttachmentDisplayOptions *)options completion:(void(^)(BOOL success))completionHandler WK_API_DEPRECATED_WITH_REPLACEMENT("-_insertAttachmentWithFileWrapper:contentType:options:completion:", macos(10.13.4, 10.14.4), ios(11.3, 12.2));
- (_WKAttachment *)_insertAttachmentWithFileWrapper:(NSFileWrapper *)fileWrapper contentType:(NSString *)contentType options:(_WKAttachmentDisplayOptions *)options completion:(void(^)(BOOL success))completionHandler WK_API_DEPRECATED_WITH_REPLACEMENT("-_insertAttachmentWithFileWrapper:contentType:completion:", macos(10.14.4, 10.14.4), ios(12.2, 12.2));
- (_WKAttachment *)_insertAttachmentWithFileWrapper:(NSFileWrapper *)fileWrapper contentType:(NSString *)contentType completion:(void(^)(BOOL success))completionHandler WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (_WKAttachment *)_attachmentForIdentifier:(NSString *)identifier WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (void)_simulateDeviceOrientationChangeWithAlpha:(double)alpha beta:(double)beta gamma:(double)gamma WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
+ (BOOL)_willUpgradeToHTTPS:(NSURL *)url WK_API_AVAILABLE(macos(12.0), ios(15.0));
+ (BOOL)_handlesSafeBrowsing WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
+ (NSURL *)_confirmMalwareSentinel WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
+ (NSURL *)_visitUnsafeWebsiteSentinel WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (void)_showSafeBrowsingWarningWithTitle:(NSString *)title warning:(NSString *)warning details:(NSAttributedString *)details completionHandler:(void(^)(BOOL))completionHandler WK_API_DEPRECATED_WITH_REPLACEMENT("-_showSafeBrowsingWarningWithURL:title:warning:detailsWithLinks:completionHandler:", macos(10.14.4, 10.15.4), ios(12.2, 13.2));
- (void)_showSafeBrowsingWarningWithURL:(NSURL *)url title:(NSString *)title warning:(NSString *)warning details:(NSAttributedString *)details completionHandler:(void(^)(BOOL))completionHandler WK_API_DEPRECATED_WITH_REPLACEMENT("-_showSafeBrowsingWarningWithURL:title:warning:detailsWithLinks:completionHandler:", macos(10.14.4, 10.15.4), ios(12.2, 13.2));
- (void)_showSafeBrowsingWarningWithURL:(NSURL *)url title:(NSString *)title warning:(NSString *)warning detailsWithLinks:(NSAttributedString *)details completionHandler:(void(^)(BOOL, NSURL *))completionHandler WK_API_AVAILABLE(macos(10.15.4), ios(13.2));
- (void)_doAfterNextPresentationUpdate:(void (^)(void))updateBlock WK_API_AVAILABLE(macos(10.12), ios(10.0));
- (void)_doAfterNextPresentationUpdateWithoutWaitingForPainting:(void (^)(void))updateBlock WK_API_AVAILABLE(macos(10.12.3), ios(10.3));
- (void)_doAfterNextVisibleContentRectUpdate:(void (^)(void))updateBlock WK_API_AVAILABLE(macos(13.0), ios(16.0));
- (void)_executeEditCommand:(NSString *)command argument:(NSString *)argument completion:(void (^)(BOOL))completion WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
- (void)_isJITEnabled:(void(^)(BOOL))completionHandler WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (void)_removeDataDetectedLinks:(dispatch_block_t)completion WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_alignCenter:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_alignJustified:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_alignLeft:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_alignRight:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_indent:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_outdent:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_toggleStrikeThrough:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_insertOrderedList:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_insertUnorderedList:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_insertNestedOrderedList:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_insertNestedUnorderedList:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_increaseListLevel:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_decreaseListLevel:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_changeListType:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_pasteAsQuotation:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_pasteAndMatchStyle:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (IBAction)_takeFindStringFromSelection:(id)sender WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
@property (class, nonatomic, copy, setter=_setStringForFind:) NSString *_stringForFind WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
@property (nonatomic, readonly) _WKSelectionAttributes _selectionAttributes WK_API_AVAILABLE(macos(10.15), ios(13.0));
- (WKNavigation *)_reloadWithoutContentBlockers WK_API_AVAILABLE(macos(10.12), ios(10.0));
- (WKNavigation *)_reloadExpiredOnly WK_API_AVAILABLE(macos(10.13), ios(11.0));
@property (nonatomic, readonly) BOOL _webProcessIsResponsive WK_API_AVAILABLE(macos(10.12), ios(10.0));
- (void)_killWebContentProcess;
- (void)_killWebContentProcessAndResetState;
- (void)_getMainResourceDataWithCompletionHandler:(void (^)(NSData *, NSError *))completionHandler;
- (void)_getWebArchiveDataWithCompletionHandler:(void (^)(NSData *, NSError *))completionHandler;
- (void)_getContentsAsStringWithCompletionHandler:(void (^)(NSString *, NSError *))completionHandler WK_API_AVAILABLE(macos(10.13), ios(11.0));
- (void)_getContentsAsStringWithCompletionHandlerKeepIPCConnectionAliveForTesting:(void (^)(NSString *, NSError *))completionHandler;
- (void)_getContentsOfAllFramesAsStringWithCompletionHandler:(void (^)(NSString *))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (void)_getContentsAsAttributedStringWithCompletionHandler:(void (^)(NSAttributedString *, NSDictionary<NSAttributedStringDocumentAttributeKey, id> *, NSError *))completionHandler WK_API_AVAILABLE(macos(10.15), ios(13.0));
- (void)_getApplicationManifestWithCompletionHandler:(void (^)(_WKApplicationManifest *))completionHandler WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
- (void)_getTextFragmentMatchWithCompletionHandler:(void (^)(NSString *))completionHandler WK_API_AVAILABLE(macos(13.3), ios(16.4));
@property (nonatomic, setter=_setPaginationMode:) _WKPaginationMode _paginationMode;
// Whether the column-break-{before,after} properties are respected instead of the
// page-break-{before,after} properties.
@property (nonatomic, setter=_setPaginationBehavesLikeColumns:) BOOL _paginationBehavesLikeColumns;
// Set to 0 to have the page length equal the view length.
@property (nonatomic, setter=_setPageLength:) CGFloat _pageLength;
@property (nonatomic, setter=_setGapBetweenPages:) CGFloat _gapBetweenPages;
@property (nonatomic, setter=_setPaginationLineGridEnabled:) BOOL _paginationLineGridEnabled;
@property (readonly) NSUInteger _pageCount;
@property (nonatomic, readonly) BOOL _supportsTextZoom;
@property (nonatomic, setter=_setTextZoomFactor:) double _textZoomFactor;
@property (nonatomic, setter=_setPageZoomFactor:) double _pageZoomFactor;
@property (nonatomic, weak, setter=_setDiagnosticLoggingDelegate:) id <_WKDiagnosticLoggingDelegate> _diagnosticLoggingDelegate WK_API_AVAILABLE(macos(10.11), ios(9.0));
@property (nonatomic, weak, setter=_setFindDelegate:) id <_WKFindDelegate> _findDelegate;
- (void)_findString:(NSString *)string options:(_WKFindOptions)options maxCount:(NSUInteger)maxCount;
- (void)_countStringMatches:(NSString *)string options:(_WKFindOptions)options maxCount:(NSUInteger)maxCount;
- (void)_hideFindUI;
@property (nonatomic, weak, setter=_setInputDelegate:) id <_WKInputDelegate> _inputDelegate WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, readonly, getter=_isDisplayingStandaloneImageDocument) BOOL _displayingStandaloneImageDocument;
@property (nonatomic, readonly, getter=_isDisplayingStandaloneMediaDocument) BOOL _displayingStandaloneMediaDocument;
@property (nonatomic, setter=_setScrollPerformanceDataCollectionEnabled:) BOOL _scrollPerformanceDataCollectionEnabled WK_API_AVAILABLE(macos(10.11), ios(9.0));
@property (nonatomic, readonly) NSArray *_scrollPerformanceData WK_API_AVAILABLE(macos(10.11), ios(9.0));
- (void)_saveBackForwardSnapshotForItem:(WKBackForwardListItem *)item WK_API_AVAILABLE(macos(10.11), ios(9.0));
@property (nonatomic, getter=_allowsMediaDocumentInlinePlayback, setter=_setAllowsMediaDocumentInlinePlayback:) BOOL _allowsMediaDocumentInlinePlayback;
@property (nonatomic, setter=_setFullscreenDelegate:) id<_WKFullscreenDelegate> _fullscreenDelegate WK_API_AVAILABLE(macos(10.13), ios(11.0));
@property (nonatomic, readonly) BOOL _isInFullscreen WK_API_AVAILABLE(macos(10.12.3));
@property (nonatomic, readonly) _WKMediaCaptureStateDeprecated _mediaCaptureState WK_API_AVAILABLE(macos(10.15), ios(13.0));
@property (nonatomic, readonly) _WKMediaMutedState _mediaMutedState WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (void)_setPageMuted:(_WKMediaMutedState)mutedState WK_API_AVAILABLE(macos(10.13), ios(11.0));
@property (nonatomic, setter=_setMediaCaptureEnabled:) BOOL _mediaCaptureEnabled WK_API_AVAILABLE(macos(10.13), ios(11.0));
- (void)_stopMediaCapture WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
@property (nonatomic, readonly) BOOL _canTogglePictureInPicture;
@property (nonatomic, readonly) BOOL _isPictureInPictureActive;
- (void)_updateMediaPlaybackControlsManager;
- (void)_togglePictureInPicture;
- (void)_stopAllMediaPlayback;
- (void)_suspendAllMediaPlayback;
- (void)_resumeAllMediaPlayback;
- (void)_closeAllMediaPresentations;
- (void)_takePDFSnapshotWithConfiguration:(WKSnapshotConfiguration *)snapshotConfiguration completionHandler:(void (^)(NSData *pdfSnapshotData, NSError *error))completionHandler WK_API_AVAILABLE(macos(10.15.4), ios(13.4));
- (void)_getPDFFirstPageSizeInFrame:(_WKFrameHandle *)frame completionHandler:(void(^)(CGSize))completionHandler WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (void)_getProcessDisplayNameWithCompletionHandler:(void (^)(NSString *))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (void)_serviceWorkersEnabled:(void(^)(BOOL))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (void)_clearServiceWorkerEntitlementOverride:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(11.0), ios(14.0));
- (void)_preconnectToServer:(NSURL *)serverURL WK_API_AVAILABLE(macos(11.0), ios(14.0));
@property (nonatomic, setter=_setCanUseCredentialStorage:) BOOL _canUseCredentialStorage WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (void)_didEnableBrowserExtensions:(NSDictionary<NSString *, NSString *> *)extensionIDToNameMap WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (void)_didDisableBrowserExtensions:(NSSet<NSString *> *)extensionIDs WK_API_AVAILABLE(macos(12.0), ios(15.0));
@property (nonatomic, weak, setter=_setAppHighlightDelegate:) id <_WKAppHighlightDelegate> _appHighlightDelegate WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (void)_restoreAppHighlights:(NSArray<NSData *> *)highlights WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (void)_restoreAndScrollToAppHighlight:(NSData *)highlight WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (void)_addAppHighlight WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (void)_addAppHighlightInNewGroup:(BOOL)newGroup originatedInApp:(BOOL)originatedInApp WK_API_AVAILABLE(macos(12.0), ios(15.0));
// FIXME: Remove old `-[WKWebView _themeColor]` SPI <rdar://76662644>
#if TARGET_OS_IPHONE
@property (nonatomic, readonly) UIColor *_themeColor WK_API_DEPRECATED_WITH_REPLACEMENT("themeColor", ios(15.0, 15.0));
#else
@property (nonatomic, readonly) NSColor *_themeColor WK_API_DEPRECATED_WITH_REPLACEMENT("themeColor", macos(12.0, 12.0));
#endif
// FIXME: Remove old `-[WKWebView _pageExtendedBackgroundColor]` SPI <rdar://77789732>
#if TARGET_OS_IPHONE
@property (nonatomic, readonly) UIColor *_pageExtendedBackgroundColor WK_API_DEPRECATED_WITH_REPLACEMENT("underPageBackgroundColor", ios(15.0, 15.0));
#else
@property (nonatomic, readonly) NSColor *_pageExtendedBackgroundColor WK_API_DEPRECATED_WITH_REPLACEMENT("underPageBackgroundColor", macos(10.10, 12.0));
#endif
// Only set if `-[WKWebViewConfiguration _sampledPageTopColorMaxDifference]` is a positive number.
#if TARGET_OS_IPHONE
@property (nonatomic, readonly) UIColor *_sampledPageTopColor WK_API_AVAILABLE(ios(15.0));
#else
@property (nonatomic, readonly) NSColor *_sampledPageTopColor WK_API_AVAILABLE(macos(12.0));
#endif
- (void)_grantAccessToAssetServices WK_API_AVAILABLE(macos(12.0), ios(14.0));
- (void)_revokeAccessToAssetServices WK_API_AVAILABLE(macos(12.0), ios(14.0));
- (void)_disableURLSchemeCheckInDataDetectors WK_API_AVAILABLE(ios(16.0));
/*! @abstract If the WKWebView was created with _shouldAllowUserInstalledFonts = NO,
the web process will automatically use an in-process font registry, and its sandbox
will be restricted to forbid access to fontd. Otherwise, the web process will use
fontd to look up fonts instead of using the in-process registry, and the web
process's sandbox will automatically be extended to allow access to fontd. This
method represents a one-time, web-process-wide switch from using the in-process
font registry to using fontd, including granting the relevant sandbox extension.
*/
- (void)_switchFromStaticFontRegistryToUserFontRegistry WK_API_AVAILABLE(macos(12.0));
- (void)_didLoadAppInitiatedRequest:(void (^)(BOOL result))completionHandler;
- (void)_didLoadNonAppInitiatedRequest:(void (^)(BOOL result))completionHandler;
- (void)_loadServiceWorker:(NSURL *)url usingModules:(BOOL)usingModules completionHandler:(void (^)(BOOL success))completionHandler WK_API_AVAILABLE(macos(13.3), ios(16.4));
- (void)_loadServiceWorker:(NSURL *)url completionHandler:(void (^)(BOOL success))completionHandler WK_API_AVAILABLE(macos(13.0), ios(16.0));
- (void)_suspendPage:(void (^)(BOOL))completionHandler WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (void)_resumePage:(void (^)(BOOL))completionHandler WK_API_AVAILABLE(macos(12.0), ios(15.0));
- (void)_startImageAnalysis:(NSString *)identifier target:(NSString *)targetIdentifier WK_API_AVAILABLE(macos(13.0), ios(16.0));
- (void)_dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void(^)(_WKDataTask *))completionHandler WK_API_AVAILABLE(macos(13.0), ios(16.0));
// Default value is 0. A value of 0 means the window's backing scale factor will be used and automatically update when the window moves screens.
@property (nonatomic, setter=_setOverrideDeviceScaleFactor:) CGFloat _overrideDeviceScaleFactor WK_API_AVAILABLE(macos(10.11), ios(16.4));
typedef NS_ENUM(NSInteger, WKDisplayCaptureState) {
WKDisplayCaptureStateNone,
WKDisplayCaptureStateActive,
WKDisplayCaptureStateMuted,
} WK_API_AVAILABLE(macos(13.0), ios(16.0));
typedef NS_ENUM(NSInteger, WKSystemAudioCaptureState) {
WKSystemAudioCaptureStateNone,
WKSystemAudioCaptureStateActive,
WKSystemAudioCaptureStateMuted,
} WK_API_AVAILABLE(macos(13.0), ios(16.0));
typedef NS_OPTIONS(NSUInteger, WKDisplayCaptureSurfaces) {
WKDisplayCaptureSurfaceNone = 0,
WKDisplayCaptureSurfaceScreen = 0x1,
WKDisplayCaptureSurfaceWindow = 0x2,
};
/*! @abstract The type(s) of displays being captured on a web page.
@discussion @link WKWebView @/link is key-value observing (KVO) compliant
for this property.
*/
@property (nonatomic, readonly) WKDisplayCaptureSurfaces _displayCaptureSurfaces WK_API_AVAILABLE(macos(13.0), ios(16.0));
/*! @abstract The state of display capture on a web page.
@discussion @link WKWebView @/link is key-value observing (KVO) compliant
for this property.
*/
@property (nonatomic, readonly) WKDisplayCaptureState _displayCaptureState WK_API_AVAILABLE(macos(13.0), ios(16.0));
/*! @abstract The state of system audio capture on a web page.
@discussion @link WKWebView @/link is key-value observing (KVO) compliant
for this property.
*/
@property (nonatomic, readonly) WKSystemAudioCaptureState _systemAudioCaptureState WK_API_AVAILABLE(macos(13.0), ios(16.0));
/*! @abstract Set display capture state of a WKWebView.
@param state State to apply for capture.
@param completionHandler A block to invoke after the screen state has been changed.
@discussion
If value is WKDisplayCaptureStateNone, this will stop all display capture.
If value is WKDisplayCaptureStateMuted, all active display captures will become muted.
If value is WKDisplayCaptureStateActive, all muted display captures will become active.
*/
- (void)_setDisplayCaptureState:(WKDisplayCaptureState)state completionHandler:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(13.0), ios(16.0));
/*! @abstract Set system audio capture state of a WKWebView.
@param state State to apply for system audio capture.
@param completionHandler A block to invoke after the system audio state has been changed.
@discussion
If value is WKSystemAudioCaptureStateNone, this will stop any system audio capture.
If value is WKSystemAudioCaptureStateMuted, any active system audio capture will become muted.
If value is WKSystemAudioCaptureStateActive, any muted system audio capture will become active.
@note When system audio capture is active, if screenCaptureState is active, all system audio will be captured.
Otherwise, if windowCaptureState is active, only the application whose window being is captured will have its audio captured.
If both screenCaptureState and windowCaptureState are None or Muted, no system audio will be captured.
*/
- (void)_setSystemAudioCaptureState:(WKSystemAudioCaptureState)state completionHandler:(void (^)(void))completionHandler WK_API_AVAILABLE(macos(13.0), ios(16.0));
+ (void)_permissionChanged:(NSString *)permissionName forOrigin:(WKSecurityOrigin *)origin WK_API_AVAILABLE(macos(13.3), ios(16.4));
/*! @abstract `YES` if any animation on the page is allowed to play.
@discussion Animations can be disallowed from starting both individually and globally. If even a single animation is allowed to play, this property will be `YES`. Calling @link _pauseAllAnimationsWithCompletionHandler @/link causes this property to become `NO`, while @link _playAllAnimationsWithCompletionHandler @/link causes it to become `YES`.
*/
@property (nonatomic, readonly) BOOL _allowsAnyAnimationToPlay WK_API_AVAILABLE(macos(13.3), ios(16.4));
/*! @abstract Pauses all animations on the page.
@discussion Calling this function also results in @link _allowsAnyAnimationToPlay @/link becoming `NO`, meaning animations loaded after a call to this function will be paused until @link _playAllAnimationsWithCompletionHandler @/link is called.
*/
- (void)_pauseAllAnimationsWithCompletionHandler:(void(^)(void))completionHandler WK_API_AVAILABLE(macos(13.3), ios(16.4));
/*! @abstract Plays all animations on the page.
@discussion Calling this function also results in @link _allowsAnyAnimationToPlay @/link becoming `YES`, meaning animations loaded after a call to this function will be allowed to begin playing.
*/
- (void)_playAllAnimationsWithCompletionHandler:(void(^)(void))completionHandler WK_API_AVAILABLE(macos(13.3), ios(16.4));
@end
#if TARGET_OS_IPHONE
#if !TARGET_OS_TV && !TARGET_OS_WATCH && __has_include(<UIKit/_UITextSearching.h>)
@interface WKWebView (WKPrivateIOS) <_UITextSearching, UITextSearching, UIFindInteractionDelegate>
#elif TARGET_OS_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= 160000
@interface WKWebView (WKPrivateIOS) <UITextSearching, UIFindInteractionDelegate>
#else
@interface WKWebView (WKPrivateIOS)
#endif
#if !TARGET_OS_TV && !TARGET_OS_WATCH
@property (nonatomic, copy, setter=_setUIEventAttribution:) UIEventAttribution *_uiEventAttribution WK_API_AVAILABLE(ios(15.0));
@property (nonatomic, copy, setter=_setEphemeralUIEventAttribution:) UIEventAttribution *_ephemeralUIEventAttribution WK_API_AVAILABLE(ios(16.0));
- (void)_setEphemeralUIEventAttribution:(UIEventAttribution *)attribution forApplicationWithBundleID:(NSString *)bundleID WK_API_AVAILABLE(ios(16.0));
#if TARGET_OS_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED >= 160000
@property (nonatomic, readonly) _UIFindInteraction *_findInteraction WK_API_AVAILABLE(ios(16.0));
@property (nonatomic, readwrite, setter=_setFindInteractionEnabled:) BOOL _findInteractionEnabled WK_API_AVAILABLE(ios(16.0));
@property (nonatomic, readonly) CALayer *_layerForFindOverlay WK_API_AVAILABLE(ios(16.0));
- (void)_requestRectForFoundTextRange:(UITextRange *)ranges completionHandler:(void (^)(CGRect))completionHandler WK_API_AVAILABLE(ios(16.0));
- (void)_addLayerForFindOverlay WK_API_AVAILABLE(ios(16.0));
- (void)_removeLayerForFindOverlay WK_API_AVAILABLE(ios(16.0));
#endif
#endif
@property (nonatomic, readonly) CGRect _contentVisibleRect WK_API_AVAILABLE(ios(10.0));
// DERECATED: The setters of the three following function are deprecated, please use overrideLayoutParameters.
// Define the smallest size a page take with a regular viewport.
@property (nonatomic, readonly) CGSize _minimumLayoutSizeOverride;
// Define the largest size the unobscured area can get for the current view bounds. This value is used to define viewport units.
@property (nonatomic, readonly) CGSize _maximumUnobscuredSizeOverride;
// Define the inset of the scrollview unusable by the web page.
@property (nonatomic, setter=_setObscuredInsets:) UIEdgeInsets _obscuredInsets;
@property (nonatomic, setter=_setUnobscuredSafeAreaInsets:) UIEdgeInsets _unobscuredSafeAreaInsets WK_API_AVAILABLE(ios(11.0));
@property (nonatomic, readonly) BOOL _safeAreaShouldAffectObscuredInsets WK_API_AVAILABLE(ios(11.0));
@property (nonatomic, setter=_setObscuredInsetEdgesAffectedBySafeArea:) UIRectEdge _obscuredInsetEdgesAffectedBySafeArea WK_API_AVAILABLE(ios(11.0));
// An ancestor view whose bounds will be intersected with those of this WKWebView to determine the visible region of content to render.
@property (nonatomic, readonly) UIView *_enclosingViewForExposedRectComputation WK_API_AVAILABLE(ios(11.0));
// Override the interface orientation. Clients using _beginAnimatedResizeWithUpdates: must update the interface orientation
// in the update block.
@property (nonatomic, setter=_setInterfaceOrientationOverride:) UIInterfaceOrientation _interfaceOrientationOverride;
- (void)_clearInterfaceOrientationOverride WK_API_AVAILABLE(ios(11.0));
@property (nonatomic, setter=_setAllowsViewportShrinkToFit:) BOOL _allowsViewportShrinkToFit;
// FIXME: Remove these three properties once we expose WKWebViewContentProvider as API.
@property (nonatomic, readonly, getter=_isDisplayingPDF) BOOL _displayingPDF;
@property (nonatomic, readonly) NSData *_dataForDisplayedPDF;
// FIXME: This can be removed once WKNavigation's response property is implemented.
@property (nonatomic, readonly) NSString *_suggestedFilenameForDisplayedPDF;
@property (nonatomic, readonly) _WKWebViewPrintFormatter *_webViewPrintFormatter;
@property (nonatomic, setter=_setDragInteractionPolicy:) _WKDragInteractionPolicy _dragInteractionPolicy WK_API_AVAILABLE(ios(11.0));
@property (nonatomic, readonly) BOOL _shouldAvoidResizingWhenInputViewBoundsChange WK_API_AVAILABLE(ios(13.0));
@property (nonatomic, readonly) BOOL _contentViewIsFirstResponder WK_API_AVAILABLE(ios(12.2));
@property (nonatomic, readonly) CGRect _uiTextCaretRect WK_API_AVAILABLE(ios(10.3));
@property (nonatomic, readonly) UIView *_safeBrowsingWarning WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
- (CGPoint)_convertPointFromContentsToView:(CGPoint)point WK_API_AVAILABLE(ios(10.0));
- (CGPoint)_convertPointFromViewToContents:(CGPoint)point WK_API_AVAILABLE(ios(10.0));
- (void)_doAfterNextStablePresentationUpdate:(dispatch_block_t)updateBlock WK_API_AVAILABLE(ios(10.3));
- (void)_setFont:(UIFont *)font sender:(id)sender WK_API_AVAILABLE(ios(12.2));
- (void)_setFontSize:(CGFloat)fontSize sender:(id)sender WK_API_AVAILABLE(ios(12.2));
- (void)_setTextColor:(UIColor *)color sender:(id)sender WK_API_AVAILABLE(ios(12.2));
- (void)_detectDataWithTypes:(WKDataDetectorTypes)types completionHandler:(dispatch_block_t)completion WK_API_AVAILABLE(ios(12.2));
- (void)_requestActivatedElementAtPosition:(CGPoint)position completionBlock:(void (^)(_WKActivatedElementInfo *))block WK_API_AVAILABLE(ios(11.0));
- (void)didStartFormControlInteraction WK_API_AVAILABLE(ios(10.3));
- (void)didEndFormControlInteraction WK_API_AVAILABLE(ios(10.3));
- (void)_beginInteractiveObscuredInsetsChange;
- (void)_endInteractiveObscuredInsetsChange;
- (void)_hideContentUntilNextUpdate;
- (void)_beginAnimatedResizeWithUpdates:(void (^)(void))updateBlock;
- (void)_endAnimatedResize;
- (void)_resizeWhileHidingContentWithUpdates:(void (^)(void))updateBlock;
- (void)_snapshotRectAfterScreenUpdates:(BOOL)afterScreenUpdates rectInViewCoordinates:(CGRect)rectInViewCoordinates intoImageOfWidth:(CGFloat)imageWidth completionHandler:(void(^)(CGImageRef))completionHandler WK_API_AVAILABLE(ios(16.0));
- (void)_snapshotRect:(CGRect)rectInViewCoordinates intoImageOfWidth:(CGFloat)imageWidth completionHandler:(void(^)(CGImageRef))completionHandler;
- (void)_overrideLayoutParametersWithMinimumLayoutSize:(CGSize)minimumLayoutSize maximumUnobscuredSizeOverride:(CGSize)maximumUnobscuredSizeOverride WK_API_AVAILABLE(ios(9_0));
- (void)_clearOverrideLayoutParameters WK_API_AVAILABLE(ios(11.0));
- (void)_overrideViewportWithArguments:(NSDictionary<NSString *, NSString *> *)arguments WK_API_AVAILABLE(ios(13.0));
- (UIView *)_viewForFindUI;
- (void)_setOverlaidAccessoryViewsInset:(CGSize)inset;
// Puts the view into a state where being taken out of the view hierarchy and resigning first responder
// will not count as becoming inactive and unfocused. The returned block must be called to exit the state.
- (void (^)(void))_retainActiveFocusedState WK_API_AVAILABLE(ios(9_0));
- (void)_becomeFirstResponderWithSelectionMovingForward:(BOOL)selectingForward completionHandler:(void (^)(BOOL didBecomeFirstResponder))completionHandler WK_API_AVAILABLE(ios(9_0));
- (id)_snapshotLayerContentsForBackForwardListItem:(WKBackForwardListItem *)item WK_API_AVAILABLE(ios(9_0));
- (NSArray *)_dataDetectionResults;
- (void)_accessibilityRetrieveRectsAtSelectionOffset:(NSInteger)offset withText:(NSString *)text completionHandler:(void (^)(NSArray<NSValue *> *rects))completionHandler WK_API_AVAILABLE(ios(11.3));
- (void)_accessibilityStoreSelection WK_API_AVAILABLE(ios(11.3));
- (void)_accessibilityClearSelection WK_API_AVAILABLE(ios(11.3));
- (void)_accessibilityRetrieveSpeakSelectionContent WK_API_AVAILABLE(ios(11.0));
- (void)_accessibilityDidGetSpeakSelectionContent:(NSString *)content WK_API_AVAILABLE(ios(11.0));
- (UIView *)_fullScreenPlaceholderView WK_API_AVAILABLE(ios(12.0));
- (void)_willOpenAppLink WK_API_AVAILABLE(ios(14.0));
- (void)_isNavigatingToAppBoundDomain:(void(^)(BOOL))completionHandler WK_API_AVAILABLE(ios(14.0));
- (void)_isForcedIntoAppBoundMode:(void(^)(BOOL))completionHandler WK_API_AVAILABLE(ios(14.0));
- (UITextInputTraits *)_textInputTraits WK_API_AVAILABLE(ios(16.4));
@end
@interface WKWebView () <UIResponderStandardEditActions>
@end
#if !TARGET_OS_WATCH
@interface WKWebView (FullScreenAPI_Private)
-(BOOL)hasFullScreenWindowController;
-(void)closeFullScreenWindowController;
@end
#endif // !TARGET_OS_WATCH
#endif // TARGET_OS_IPHONE
#if !TARGET_OS_IPHONE
@interface WKWebView (WKPrivateMac)
@property (nonatomic, readonly) WKPageRef _pageRefForTransitionToWKWebView WK_API_AVAILABLE(macos(10.13.4));
@property (nonatomic, readonly) BOOL _hasActiveVideoForControlsManager WK_API_AVAILABLE(macos(10.12));
@property (nonatomic, readwrite, setter=_setIgnoresNonWheelEvents:) BOOL _ignoresNonWheelEvents WK_API_AVAILABLE(macos(10.13.4));
@property (nonatomic, readwrite, setter=_setIgnoresMouseMoveEvents:) BOOL _ignoresMouseMoveEvents WK_API_AVAILABLE(macos(13.0));
/*! @abstract A Boolean value indicating whether drawing clips to the visibleRect.
@discussion When YES, the view will use its -visibleRect when determining which areas of the WKWebView to draw. This may improve performance for large WKWebViews which are mostly clipped out by enclosing views. The default value is NO.
*/
@property (nonatomic, readwrite, setter=_setClipsToVisibleRect:) BOOL _clipsToVisibleRect WK_API_AVAILABLE(macos(11.0));
@property (nonatomic, readonly) NSView *_safeBrowsingWarning WK_API_AVAILABLE(macos(10.14.4));
@property (nonatomic, readonly) _WKRectEdge _pinnedState WK_API_AVAILABLE(macos(10.13.4));
@property (nonatomic, setter=_setRubberBandingEnabled:) _WKRectEdge _rubberBandingEnabled WK_API_AVAILABLE(macos(10.13.4));
@property (nonatomic, setter=_setBackgroundColor:) NSColor *_backgroundColor WK_API_AVAILABLE(macos(10.14));
@property (nonatomic, copy, setter=_setUnderlayColor:) NSColor *_underlayColor WK_API_AVAILABLE(macos(10.13.4));
@property (nonatomic, setter=_setTotalHeightOfBanners:) CGFloat _totalHeightOfBanners WK_API_AVAILABLE(macos(10.13.4));
@property (nonatomic, setter=_setDrawsBackground:) BOOL _drawsBackground;
@property (nonatomic, setter=_setTopContentInset:) CGFloat _topContentInset;
@property (nonatomic, setter=_setAutomaticallyAdjustsContentInsets:) BOOL _automaticallyAdjustsContentInsets;
@property (nonatomic, setter=_setWindowOcclusionDetectionEnabled:) BOOL _windowOcclusionDetectionEnabled;
@property (nonatomic, readonly) NSInteger _spellCheckerDocumentTag WK_API_AVAILABLE(macos(10.14));
// When using _minimumLayoutWidth, the web content will lay out to the intrinsic height
// of the content; use this property to force it to lay out to the height of the view instead.
@property (nonatomic, setter=_setShouldExpandContentToViewHeightForAutoLayout:) BOOL _shouldExpandContentToViewHeightForAutoLayout WK_API_AVAILABLE(macos(10.12));
@property (nonatomic, setter=_setMinimumLayoutWidth:) CGFloat _minimumLayoutWidth WK_API_AVAILABLE(macos(10.12));
@property (nonatomic, setter=_setSizeToContentAutoSizeMaximumSize:) CGSize _sizeToContentAutoSizeMaximumSize;
@property (nonatomic, setter=_setAlwaysShowsHorizontalScroller:) BOOL _alwaysShowsHorizontalScroller WK_API_AVAILABLE(macos(10.13.4));
@property (nonatomic, setter=_setAlwaysShowsVerticalScroller:) BOOL _alwaysShowsVerticalScroller WK_API_AVAILABLE(macos(10.13.4));
@property (nonatomic, readwrite, setter=_setUseSystemAppearance:) BOOL _useSystemAppearance WK_API_AVAILABLE(macos(10.14));
@property (nonatomic, setter=_setOverlayScrollbarStyle:) _WKOverlayScrollbarStyle _overlayScrollbarStyle WK_API_AVAILABLE(macos(10.13.4));
@property (strong, nonatomic, setter=_setInspectorAttachmentView:) NSView *_inspectorAttachmentView WK_API_AVAILABLE(macos(10.13.4));
@property (nonatomic, setter=_setHeaderBannerLayer:) CALayer *_headerBannerLayer;
@property (nonatomic, setter=_setFooterBannerLayer:) CALayer *_footerBannerLayer;
@property (nonatomic, setter=_setThumbnailView:) _WKThumbnailView *_thumbnailView WK_API_AVAILABLE(macos(10.13.4));
@property (nonatomic, setter=_setIgnoresAllEvents:) BOOL _ignoresAllEvents WK_API_AVAILABLE(macos(10.13.4));
// Defaults to YES; if set to NO, WebKit will draw the grey wash and highlights itself.
@property (nonatomic, setter=_setUsePlatformFindUI:) BOOL _usePlatformFindUI WK_API_AVAILABLE(macos(10.15));
- (void)_setShouldSuppressFirstResponderChanges:(BOOL)shouldSuppress;
- (BOOL)_canChangeFrameLayout:(_WKFrameHandle *)frameHandle WK_API_AVAILABLE(macos(10.13.4));
- (BOOL)_tryToSwipeWithEvent:(NSEvent *)event ignoringPinnedState:(BOOL)ignoringPinnedState WK_API_AVAILABLE(macos(10.13.4));
- (void)_dismissContentRelativeChildWindows WK_API_AVAILABLE(macos(10.13.4));
- (void)_setFrame:(NSRect)rect andScrollBy:(NSSize)offset WK_API_AVAILABLE(macos(10.13.4));
- (void)_gestureEventWasNotHandledByWebCore:(NSEvent *)event WK_API_AVAILABLE(macos(10.13.4));
- (void)_disableFrameSizeUpdates WK_API_AVAILABLE(macos(10.13.4));
- (void)_enableFrameSizeUpdates WK_API_AVAILABLE(macos(10.13.4));
- (void)_beginDeferringViewInWindowChanges WK_API_AVAILABLE(macos(10.13.4));
- (void)_endDeferringViewInWindowChanges WK_API_AVAILABLE(macos(10.13.4));
- (void)_endDeferringViewInWindowChangesSync WK_API_AVAILABLE(macos(10.13.4));
- (void)_setCustomSwipeViews:(NSArray *)customSwipeViews WK_API_AVAILABLE(macos(10.13.4));
- (void)_setDidMoveSwipeSnapshotCallback:(void(^)(CGRect))callback WK_API_AVAILABLE(macos(10.13.4));
- (void)_setCustomSwipeViewsTopContentInset:(float)topContentInset WK_API_AVAILABLE(macos(10.13.4));
- (NSView *)_fullScreenPlaceholderView WK_API_AVAILABLE(macos(10.13.4));
- (NSWindow *)_fullScreenWindow WK_API_AVAILABLE(macos(10.13.4));
// Clients that want to maintain default behavior can return nil. To disable the immediate action entirely, return NSNull. And to
// do something custom, return an object that conforms to the NSImmediateActionAnimationController protocol.
- (id)_immediateActionAnimationControllerForHitTestResult:(_WKHitTestResult *)hitTestResult withType:(_WKImmediateActionType)type userData:(id<NSSecureCoding>)userData;
- (NSPrintOperation *)_printOperationWithPrintInfo:(NSPrintInfo *)printInfo;
- (NSPrintOperation *)_printOperationWithPrintInfo:(NSPrintInfo *)printInfo forFrame:(_WKFrameHandle *)frameHandle WK_API_AVAILABLE(macos(10.12));
// FIXME: This SPI should become a part of the WKUIDelegate. rdar://problem/26561537
@property (nonatomic, readwrite, setter=_setWantsMediaPlaybackControlsView:) BOOL _wantsMediaPlaybackControlsView WK_API_AVAILABLE(macos(10.12.3));
@property (nonatomic, readonly) id _mediaPlaybackControlsView WK_API_AVAILABLE(macos(10.13));
- (void)_addMediaPlaybackControlsView:(id)mediaPlaybackControlsView WK_API_AVAILABLE(macos(10.13));
- (void)_removeMediaPlaybackControlsView WK_API_AVAILABLE(macos(10.12.3));
- (void)_prepareForMoveToWindow:(NSWindow *)targetWindow completionHandler:(void(^)(void))completionHandler WK_API_AVAILABLE(macos(10.13));
- (void)_simulateMouseMove:(NSEvent *)event WK_API_AVAILABLE(macos(13.0));
- (void)_setFont:(NSFont *)font sender:(id)sender WK_API_AVAILABLE(macos(13.3));
@end
#endif // !TARGET_OS_IPHONE

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <WebKit/WKFoundation.h>
#if TARGET_OS_IPHONE
@class UIImage;
#else
@class NSImage;
#endif
typedef NS_ENUM(NSInteger, _WKActivatedElementType) {
_WKActivatedElementTypeLink,
_WKActivatedElementTypeImage,
_WKActivatedElementTypeAttachment WK_API_AVAILABLE(macos(10.12), ios(10.0)),
_WKActivatedElementTypeUnspecified WK_API_AVAILABLE(macos(10.13), ios(11.0)),
} WK_API_AVAILABLE(macos(10.10), ios(8.0));
WK_CLASS_AVAILABLE(macos(10.10), ios(8.0))
@interface _WKActivatedElementInfo : NSObject
@property (nonatomic, readonly) NSURL *URL;
@property (nonatomic, readonly) NSURL *imageURL;
@property (nonatomic, readonly) NSString *title;
@property (nonatomic, readonly) _WKActivatedElementType type;
@property (nonatomic, readonly) CGRect boundingRect;
@property (nonatomic, readonly) NSString *ID WK_API_AVAILABLE(macos(10.12), ios(10.0));
@property (nonatomic, readonly) BOOL isAnimatedImage WK_API_AVAILABLE(macos(10.15), ios(13.0));
#if TARGET_OS_IPHONE
@property (nonatomic, readonly) BOOL isAnimating;
@property (nonatomic, readonly) BOOL canShowAnimationControls;
@property (nonatomic, readonly) NSDictionary *userInfo WK_API_AVAILABLE(ios(11.0));
@property (nonatomic, readonly, copy) UIImage *image;
#else
@property (nonatomic, readonly, copy) NSImage *image;
#endif
@end

View File

@@ -0,0 +1,65 @@
/*
* Copyright (C) 2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <WebKit/WKFoundation.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, _WKAttachmentDisplayMode) {
_WKAttachmentDisplayModeAuto = 1,
_WKAttachmentDisplayModeInPlace,
_WKAttachmentDisplayModeAsIcon
} WK_API_AVAILABLE(macos(10.13.4), ios(11.3));
WK_CLASS_AVAILABLE(macos(10.13.4), ios(11.3))
@interface _WKAttachmentDisplayOptions : NSObject
@property (nonatomic) _WKAttachmentDisplayMode mode;
@end
WK_CLASS_AVAILABLE(macos(10.14), ios(12.0))
@interface _WKAttachmentInfo : NSObject
@property (nonatomic, readonly, nullable) NSString *contentType;
@property (nonatomic, readonly, nullable) NSString *name;
@property (nonatomic, readonly, nullable) NSString *filePath;
@property (nonatomic, readonly, nullable) NSData *data;
@property (nonatomic, readonly, nullable) NSFileWrapper *fileWrapper;
@end
WK_CLASS_AVAILABLE(macos(10.13.4), ios(11.3))
@interface _WKAttachment : NSObject
- (void)setFileWrapper:(NSFileWrapper *)fileWrapper contentType:(nullable NSString *)contentType completion:(void(^ _Nullable)(NSError * _Nullable))completionHandler WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
@property (nonatomic, readonly, nullable) _WKAttachmentInfo *info WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
@property (nonatomic, readonly) NSString *uniqueIdentifier;
@property (nonatomic, readonly, getter=isConnected) BOOL connected WK_API_AVAILABLE(macos(10.14.4), ios(12.2));
// Deprecated SPI.
- (void)requestInfo:(void(^)(_WKAttachmentInfo * _Nullable, NSError * _Nullable))completionHandler WK_API_DEPRECATED_WITH_REPLACEMENT("-info", macos(10.14, 10.14.4), ios(12.0, 12.2));
- (void)setData:(NSData *)data newContentType:(nullable NSString *)newContentType newFilename:(nullable NSString *)newFilename completion:(void(^ _Nullable)(NSError * _Nullable))completionHandler WK_API_DEPRECATED_WITH_REPLACEMENT("Please use -setFileWrapper:contentType:completion: instead.", macos(10.13.4, 10.14.4), ios(11.3, 12.2));
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,41 @@
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#import <WebKit/WKFoundation.h>
#import <Foundation/Foundation.h>
@protocol _WKFindDelegate <NSObject>
@optional
- (void)_webView:(WKWebView *)webView didCountMatches:(NSUInteger)matches forString:(NSString *)string;
- (void)_webView:(WKWebView *)webView didFindMatches:(NSUInteger)matches forString:(NSString *)string withMatchIndex:(NSInteger)matchIndex;
- (void)_webView:(WKWebView *)webView didFailToFindString:(NSString *)string;
- (void)_webView:(WKWebView *)webView didAddLayerForFindOverlay:(CALayer *)layer;
- (void)_webViewDidRemoveLayerForFindOverlay:(WKWebView *)webView;
@end

Some files were not shown because too many files have changed in this diff Show More