2021-02-17 18:28:18 -08:00
|
|
|
//
|
|
|
|
|
// BrowserViewController+WebKitDelegate.swift
|
|
|
|
|
// App
|
|
|
|
|
//
|
|
|
|
|
// Created by James Magahern on 2/17/21.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
import WebKit
|
|
|
|
|
|
|
|
|
|
extension BrowserViewController: WKNavigationDelegate, WKUIDelegate
|
|
|
|
|
{
|
|
|
|
|
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
|
2024-08-05 17:36:59 -07:00
|
|
|
if let tab = tabController.tab(forWebView: webView) {
|
|
|
|
|
// We're alive!
|
|
|
|
|
tab.contentProcessTerminated = false
|
|
|
|
|
tab.loadError = nil
|
|
|
|
|
}
|
2021-02-17 18:28:18 -08:00
|
|
|
|
|
|
|
|
// Check to make sure we have connected to the web content process
|
2024-07-29 19:21:51 -07:00
|
|
|
if !currentTab.bridge.webContentProcessConnected {
|
2021-02-17 18:28:18 -08:00
|
|
|
// 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
|
2024-07-29 19:21:51 -07:00
|
|
|
currentTab.allowedScriptOrigins.removeAll()
|
|
|
|
|
currentTab.blockedScriptOrigins.removeAll()
|
2021-02-17 18:28:18 -08:00
|
|
|
updateScriptBlockerButton()
|
|
|
|
|
|
|
|
|
|
// Blur url bar if applicable
|
|
|
|
|
toolbarController.urlBar.textField.resignFirstResponder()
|
|
|
|
|
|
|
|
|
|
updateTitleAndURL(forWebView: webView)
|
|
|
|
|
|
|
|
|
|
if let url = webView.url {
|
|
|
|
|
// Start requesting favicon
|
2024-07-29 19:21:51 -07:00
|
|
|
currentTab.updateFaviconForURL(url)
|
2021-02-17 18:28:18 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-07-13 16:47:24 -07:00
|
|
|
func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
|
|
|
|
|
// We got rugged!!!!!! Update the favicon again.
|
|
|
|
|
if let url = webView.url {
|
|
|
|
|
// Start requesting favicon
|
2024-07-29 19:21:51 -07:00
|
|
|
currentTab.updateFaviconForURL(url)
|
2021-07-13 16:47:24 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-17 18:28:18 -08:00
|
|
|
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
|
|
|
|
|
toolbarController.urlBar.loadProgress = .complete
|
|
|
|
|
|
|
|
|
|
// Update history
|
|
|
|
|
if let url = webView.url {
|
|
|
|
|
let title = webView.title ?? ""
|
|
|
|
|
BrowserHistory.shared.didNavigate(toURL: url, title: title)
|
|
|
|
|
}
|
2022-08-05 18:55:19 -07:00
|
|
|
|
|
|
|
|
// Publish Tabs
|
|
|
|
|
AttractorServer.shared.publishTabInfo(tabController.tabs.map { $0.tabInfo })
|
2021-02-17 18:28:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, preferences: WKWebpagePreferences, decisionHandler: @escaping (WKNavigationActionPolicy, WKWebpagePreferences) -> Void)
|
|
|
|
|
{
|
|
|
|
|
// Handle command+click
|
|
|
|
|
if (commandKeyHeld || windowButtonHeld) && navigationAction.navigationType == .linkActivated {
|
|
|
|
|
// Cancel navigation in this tab
|
|
|
|
|
decisionHandler(.cancel, preferences)
|
|
|
|
|
|
|
|
|
|
// Start navigation in a new tab
|
2022-02-21 16:01:01 -08:00
|
|
|
createNewTab(withURL: navigationAction.request.url, loadInBackground: self.shiftKeyHeld)
|
2021-02-17 18:28:18 -08:00
|
|
|
|
|
|
|
|
// Reset this flag.
|
|
|
|
|
commandKeyHeld = false
|
|
|
|
|
windowButtonHeld = false
|
|
|
|
|
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-29 19:21:51 -07:00
|
|
|
var allowJavaScript = currentTab.javaScriptEnabled
|
2021-02-17 18:28:18 -08:00
|
|
|
if !allowJavaScript, let host = navigationAction.request.url?.host {
|
|
|
|
|
// Check origin policy
|
2021-10-21 13:24:58 -07:00
|
|
|
allowJavaScript = policyManager.scriptPolicy(forOrigin: host).allowsEmbeddedJavaScript()
|
2021-02-17 18:28:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
preferences.allowsContentJavaScript = allowJavaScript
|
|
|
|
|
|
|
|
|
|
if let url = navigationAction.request.url,
|
2021-12-14 18:50:33 -08:00
|
|
|
let redirectedURL = Settings.shared.redirectRule(for: url)
|
2021-02-17 18:28:18 -08:00
|
|
|
{
|
2024-07-29 19:21:51 -07:00
|
|
|
currentTab.beginLoadingURL(redirectedURL)
|
2021-02-17 18:28:18 -08:00
|
|
|
decisionHandler(.cancel, preferences)
|
|
|
|
|
} else {
|
|
|
|
|
decisionHandler(.allow, preferences)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
|
2024-07-29 19:21:51 -07:00
|
|
|
if webView == currentTab.webView {
|
|
|
|
|
currentTab.loadError = error
|
2021-05-06 16:42:04 -07:00
|
|
|
}
|
2021-02-17 18:28:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
|
2024-07-29 19:21:51 -07:00
|
|
|
if webView == currentTab.webView {
|
|
|
|
|
currentTab.loadError = error
|
2021-05-06 16:42:04 -07:00
|
|
|
}
|
2021-02-17 18:28:18 -08:00
|
|
|
}
|
|
|
|
|
|
2024-08-05 17:36:59 -07:00
|
|
|
func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
|
|
|
|
|
tabController.tab(forWebView: webView)?.contentProcessTerminated = true
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-17 18:28:18 -08:00
|
|
|
// MARK: WKUIDelegate
|
|
|
|
|
|
|
|
|
|
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView?
|
|
|
|
|
{
|
|
|
|
|
let newTab = tabController.createNewTab(url: nil, webViewConfiguration: configuration)
|
|
|
|
|
newTab.webView.load(navigationAction.request)
|
|
|
|
|
|
2024-07-29 19:21:51 -07:00
|
|
|
self.currentTab = newTab
|
2021-02-17 18:28:18 -08:00
|
|
|
|
|
|
|
|
return newTab.webView
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func webView(_ webView: WKWebView, contextMenuConfigurationForElement elementInfo: WKContextMenuElementInfo, completionHandler: @escaping (UIContextMenuConfiguration?) -> Void) {
|
|
|
|
|
let menuConfig = UIContextMenuConfiguration(identifier: nil,
|
|
|
|
|
previewProvider: nil) { (menuElements: [UIMenuElement]) -> UIMenu? in
|
|
|
|
|
|
|
|
|
|
let openInNewTab = UIAction(title: "Open in New Tab",
|
|
|
|
|
image: UIImage(systemName: "plus.app"),
|
|
|
|
|
identifier: nil,
|
|
|
|
|
discoverabilityTitle: nil,
|
|
|
|
|
attributes: [],
|
|
|
|
|
state: .off) { [unowned self] _ in
|
2022-02-21 16:01:01 -08:00
|
|
|
self.createNewTab(withURL: elementInfo.linkURL, loadInBackground: false)
|
2021-02-17 18:28:18 -08:00
|
|
|
}
|
|
|
|
|
|
2022-02-21 16:01:01 -08:00
|
|
|
let openInBackground = UIAction(title: "Open in Background",
|
|
|
|
|
image: UIImage(systemName: "plus.rectangle.on.rectangle"),
|
|
|
|
|
identifier: nil,
|
|
|
|
|
discoverabilityTitle: nil,
|
|
|
|
|
attributes: [],
|
|
|
|
|
state: .off) { [unowned self] _ in
|
|
|
|
|
self.createNewTab(withURL: elementInfo.linkURL, loadInBackground: true)
|
|
|
|
|
}
|
2021-02-17 18:28:18 -08:00
|
|
|
|
|
|
|
|
return UIMenu(title: elementInfo.linkURL?.absoluteString ?? "Link",
|
|
|
|
|
image: nil,
|
|
|
|
|
identifier: nil,
|
|
|
|
|
options: .displayInline,
|
2022-02-21 16:01:01 -08:00
|
|
|
children: [ openInNewTab, openInBackground ] + menuElements)
|
2021-02-17 18:28:18 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
completionHandler(menuConfig)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|