Last active
February 15, 2022 13:54
-
-
Save funkydevil/fc03f05ff921d6b5daac8f93d91319f6 to your computer and use it in GitHub Desktop.
JS injections, SWIFT->JS, JS->SWIFT
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE HTML> | |
<html> | |
<head> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<style> | |
.block { | |
display: block; | |
width: 100%; | |
border: none; | |
background-color: #04AA6D; | |
color: white; | |
padding: 14px 28px; | |
font-size: 16px; | |
cursor: pointer; | |
text-align: center; | |
} | |
.block:hover { | |
background-color: #ddd; | |
color: black; | |
} | |
</style> | |
</head> | |
<body> | |
<button onclick="showAlert()" class="block">Show alert</button> | |
<button onclick="createTextField()" class="block">createTextField</button> | |
<button onclick="swiftFunction()" class="block">call swiftFunction</button> | |
<button onclick="injectedFunction()" class="block">call injectedFunction</button> | |
<script> | |
function showAlert() { | |
alert( 'hello world!' ); | |
} | |
function createTextField() { | |
var x = document.createElement("INPUT"); | |
x.setAttribute("type", "text"); | |
x.setAttribute("value", "Hello World!"); | |
document.body.appendChild(x); | |
} | |
function getValueFromJS() { | |
return "hello"; | |
} | |
function swiftFunction() { | |
window.webkit.messageHandlers.testFunc.postMessage({param1: "111", param2: "222"}); | |
} | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ViewController.swift | |
// JSCallExample | |
// | |
// Created by Kirill Pyulzyu on 15.02.2022. | |
// | |
import UIKit | |
import WebKit | |
class ViewController: UIViewController { | |
var webview: WKWebView! | |
let jsHandler = "testFunc" | |
override func viewDidLoad() { | |
super.viewDidLoad() | |
// Do any additional setup after loading the view. | |
addWKWebView() | |
loadHTML() | |
} | |
func addWKWebView() { | |
let width = self.view.frame.width | |
let height = self.view.frame.height | |
let webviewFrame = CGRect(x: 0, y: height/2, width: width, height: height/2) | |
let contentController = WKUserContentController() | |
let scriptSource = "function injectedFunction() { alert('testtest') }" | |
let script = WKUserScript(source: scriptSource, injectionTime: .atDocumentEnd, forMainFrameOnly: true) | |
contentController.addUserScript(script) | |
let configuration = WKWebViewConfiguration() | |
configuration.userContentController = contentController | |
configuration.userContentController.add(self, name: jsHandler) | |
webview = WKWebView(frame: webviewFrame, configuration: configuration) | |
webview.uiDelegate = self | |
view.addSubview(webview) | |
} | |
func loadHTML() { | |
guard let webview = webview else { | |
return | |
} | |
let url = Bundle.main.url(forResource: "index.html", withExtension: nil)! | |
webview.loadFileURL(url, allowingReadAccessTo: url) | |
} | |
@IBAction func onCallJSTapped(_ sender: Any) { | |
webview?.evaluateJavaScript("createTextField()", completionHandler: { result, error in | |
}) | |
} | |
@IBAction func getValueFromJS(_ sender: Any) { | |
webview?.evaluateJavaScript("getValueFromJS()", completionHandler: { result, error in | |
print(result!) | |
}) | |
} | |
} | |
extension ViewController: WKScriptMessageHandler { | |
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { | |
if message.name == jsHandler { | |
guard let params = message.body as? [String: String] else { | |
return | |
} | |
for (key, value) in params { | |
print(key + " = " + value) | |
} | |
} | |
} | |
} | |
extension ViewController: WKUIDelegate { | |
func webView(_ webView: WKWebView, runJavaScriptAlertPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, | |
completionHandler: @escaping () -> Void) { | |
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet) | |
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in | |
completionHandler() | |
})) | |
present(alertController, animated: true, completion: nil) | |
} | |
func webView(_ webView: WKWebView, runJavaScriptConfirmPanelWithMessage message: String, initiatedByFrame frame: WKFrameInfo, | |
completionHandler: @escaping (Bool) -> Void) { | |
let alertController = UIAlertController(title: nil, message: message, preferredStyle: .actionSheet) | |
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in | |
completionHandler(true) | |
})) | |
alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in | |
completionHandler(false) | |
})) | |
present(alertController, animated: true, completion: nil) | |
} | |
func webView(_ webView: WKWebView, runJavaScriptTextInputPanelWithPrompt prompt: String, defaultText: String?, initiatedByFrame frame: WKFrameInfo, | |
completionHandler: @escaping (String?) -> Void) { | |
let alertController = UIAlertController(title: nil, message: prompt, preferredStyle: .actionSheet) | |
alertController.addTextField { (textField) in | |
textField.text = defaultText | |
} | |
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action) in | |
if let text = alertController.textFields?.first?.text { | |
completionHandler(text) | |
} else { | |
completionHandler(defaultText) | |
} | |
})) | |
alertController.addAction(UIAlertAction(title: "Cancel", style: .default, handler: { (action) in | |
completionHandler(nil) | |
})) | |
present(alertController, animated: true, completion: nil) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment